目录
一、警告
1、错误的代码
2、正确的代码
3、解决办法
二、示例
1、必要的定义
2、错误的代码书写
3、正确的代码书写
在数组或结构体初始化时,编译器检测到初始化列表没有用大括号明确区分每个元素的初始化值,即初始化列表中的元素没有被正确地用大括号包围,导致编译器无法准确解析每个元素的初始值。 详见本文作者写的的其它文章:警告warning: missing braces around initializer [-Wmissing-braces]的解决办法-CSDN博客 https://wenchm.blog.csdn.net/article/details/146395354?spm=1011.2415.3001.5331。
同样地, 在数组或结构体初始化时,如果在初始化一个标量(如一个整数、浮点数或指针)时使用了花括号 {}
而不是单个值,编译器也会发出警告:“warning: braces around scalar initializer”。
一、警告
在 C 或 C++ 编程中,当你看到警告“warning: braces around scalar initializer”时,这通常意味着你在初始化一个标量(如一个整数、浮点数或指针)时使用了花括号 {}
而不是单个值。标量初始化应该使用单个值而不是花括号。
在 C99 和 C++11 标准中,对于数组和结构体,使用花括号初始化是推荐的做法,因为这可以更清晰地表达初始化内容。但对于标量(单个变量),这种用法是不必要的,并且可能导致混淆。标量应该直接使用单个值进行初始化。
1、错误的代码
int x = {5}; // 错误:标量不应该使用花括号
2、正确的代码
int x = 5; // 正确:使用单个值初始化标量
3、解决办法
确保在初始化标量时仅使用单个值,而不是花括号。如果代码中有类似 {...}
的初始化表达式,应该检查这些表达式是否真的需要花括号,或者是否应该简化为单个值。
比如:
int array[] = {1, 2, 3, 4}; // 正确:数组初始化可以使用花括号
int scalar = {5}; // 错误:标量不应该使用花括号
应该修改为:
int array[] = {1, 2, 3, 4}; // 正确:数组初始化
int scalar = 5; // 正确:标量初始化使用单个值
二、示例
以下是摘录一段与本文警告有关的应用程序,源程序比较复杂,在书写时曾遭遇本文提到的警告,先分享如下:
1、必要的定义
//本例中必要的结构体、联合体定义//面板结构体类型定义
typedef struct{STR_KEYSCAN KeyScan;STR_PANELMENU Menu;STR_LEDDISPLAY Display;
}STR_PANELOPERRATION;//扫描按键结构体类型定义
typedef struct{volatile UNI_SPIRXKEY_REG Input; //输入信号volatile UNI_SPIRXKEY_REG FltrInput; //经滤波后的输入信号ENU_KEYVAULE CurrKey; //当前键扫描的值ENU_KEYEDGESTATUS KeyEdge; //当前键边沿状态Uint8 ModeFltrCnt; //MODE键滤波计数器Uint8 UpFltrCnt; //UP键滤波计数器Uint8 DownFltrCnt; //DOWN键滤波计数器Uint8 ShiftFltrCnt; /SHIFT键滤波计数器Uint8 SetFltrCnt; //SET键滤波计数器Uint8 AccCnt; //UP键和DOWN键加速计数器Uint8 AccLevel; //UP键和DOWN键加速等级Uint8 AccLevelCnt; //UP键和DOWN键加速等级计数器
}STR_KEYSCAN;typedef union{volatile Uint8 all;volatile STR_SPIRXKEY_Bit bit;
}UNI_SPIRXKEY_REG; // 键值定义
typedef enum{MODEKEY = 0,UPKEY = 1,DOWNKEY = 2, SHIFTKEY = 3,LONG_SHIFTKEY = 4,SETKEY = 5,LONG_SETKEY = 6,UPDOWNKEY = 7,NONEKEY = 8,
}ENU_KEYVAULE; //键状态定义
typedef enum{INVALIDEDGE = 0,VALIDEDGE = 1,
}ENU_KEYEDGESTATUS;//面板菜单结构体类型定义
typedef struct{volatile UNI_PANELMENUCTRL_REG CtrlReg; //面板菜单控制寄存器int8 DispGroup; //显示功能码组int8 DispOffset; //显示功能码组内偏移Uint32 DispData; //LED数码管显示数据Uint16 UserPass; //用户密码
}STR_PANELMENU;typedef union{volatile Uint16 all;volatile STR_PANELMENUCTRL_BIT bit;
}UNI_PANELMENUCTRL_REG;//面板菜单控制位定义
typedef struct{Uint16 ErrShowSure:1; //故障确认标志位Uint16 Class:4; //面板菜单等级Uint16 Page:2; //面板菜单显示页数Uint16 Class3rdMode:4; //面板第三级菜单显示模式Uint16 DealBit:4; //面板正在操作的LED数码管位Uint16 Class2ndDisp_SAVE:1; //第二级菜单显示SAVE标志位 0 不显示 1 显示
}STR_PANELMENUCTRL_BIT; //LED显示结构体类型定义
typedef struct{Uint8 DispData[5]; //LED数码管显示段数据volatile UNI_LEDDISPLAYCTRL_REG CtrlReg; //控制寄存器Uint8 Timer; //定时器,闪烁时使用Uint8 TubeIndex; //当前显示的数码管序号Uint8 TxTubeSel; //发送当前显示的数码管使能Uint8 TxDispData; //发送当前显示的数码管数据
}STR_LEDDISPLAY;typedef union{volatile Uint8 all;volatile STR_LEDDISPLAYCTRL_BIT bit;
}UNI_LEDDISPLAYCTRL_REG;//LED显示控制寄存器定义
typedef struct{Uint8 ZeroFlicker:1; //第0位数据闪烁控制位 0:不闪烁, 1:闪烁Uint8 FirstFlicker:1; //第1位数据闪烁控制位 0:不闪烁, 1:闪烁Uint8 SecondFlicker:1; //第2位数据闪烁控制位 0:不闪烁, 1:闪烁Uint8 ThirdFlicker:1; //第3位数据闪烁控制位 0:不闪烁, 1:闪烁Uint8 ForthFlicker:1; //第4位数据闪烁控制位 0:不闪烁, 1:闪烁Uint8 DotFlicker:1; //小数点闪烁控制位 0:正常, 1:永远都不闪烁Uint8 Rsvd:2; //保留
}STR_LEDDISPLAYCTRL_BIT;
2、错误的代码书写
宏定义PANELOPERRATION_DEFAULT的数据类型是STR_PANELOPERRATION结构体,并且结构体STR_PANELOPERRATION成员由另外的三个结构体构成。
//错误的代码书写,过多地使用了{}
#define PANELOPERRATION_DEFAULT \{ \{{0xFF},{0xFF},{NONEKEY},{INVALIDEDGE},0,0,0,0,0,0,ACCLEVEL1ST,0}, \{{0},0,0,0,0}, \{{0xaf,0x86,0x92,0x86,0x87},{0},0,0,0,0}\}/* 变量定义 */
STR_PANELOPERRATION ServoPanel = PANELOPERRATION_DEFAULT;
3、正确的代码书写
//正确的代码书写,去除过多的{}/*PANELOPERRATION_DEFAULT的构成 */
/*STR_KEYSCAN,12个成员,前2个成员是结构体,ENUM数值除外 */
/*STR_PANELMENU,5个成员。第1个成员是联合体*/
/*STR_LEDDISPLAY,6个成员,第1个成员是数组,第2个成员是联合体 */
#define PANELOPERRATION_DEFAULT \{ \{{0xFF},{0xFF},NONEKEY,INVALIDEDGE,0,0,0,0,0,0,ACCLEVEL1ST,0}, \{{0},0,0,0,0}, \{{0xaf,0x86,0x92,0x86,0x87},{0},0,0,0,0}\}/* 变量定义 */
STR_PANELOPERRATION ServoPanel = PANELOPERRATION_DEFAULT;
总之,遇到“warning: braces around scalar initializer”这样的警告时,就是{}用错了地方。检查代码,确保标量的初始化是直接使用单个值而不是花括号。就可以避免不必要的编译器警告,并使代码更加清晰和符合标准。