为何填充结构体的辅助宏需要显式类型转换?
GCC中结构体初始化宏在赋值语句的语法问题及修复
咱们来看下面这段C代码:
struct my_cool_struc { int field_x; int field_Y; int field_z; }; #define MY_COOL_MACRO(x,y,z) \ { \ .field_x = (x), \ .field_y = (y), \ .field_z = (z), \ } static const struct my_cool_struc why[] = { MY_COOL_MACRO(1,2,3), MY_COOL_MACRO(6,5,4), MY_COOL_MACRO(7,8,9), {} }; static int my_cool_func(...) { struct my_cool_struc p[10]; int a1, a2, a3; unsigned int index = 0; ... p[index++] = MY_COOL_MACRO(a1, a2, a3); ... return 0; }
你会发现一个有意思的现象:在全局数组why的初始化代码里,用MY_COOL_MACRO完全能正常编译;但到了my_cool_func函数里,那句赋值语句p[index++] = MY_COOL_MACRO(a1, a2, a3);却会触发语法解析错误,在Linux环境下的不同版本GCC里都是如此。
原因解析
这其实是C语言语法规则的限制:在数组或结构体的初始化列表中,{}包裹的聚合初始化语法是合法的;但在赋值表达式的右侧,单独的{}聚合体并不是一个有效的右值,GCC不允许直接把这种聚合初始化语法当作值来赋值给变量,必须显式地将其转换为对应的结构体类型。
两种修复方案
方案1:修改宏定义,内置类型转换
直接给宏生成的聚合初始化代码加上结构体类型的强制转换,这样宏调用的结果本身就是一个合法的结构体右值:
#define MY_COOL_MACRO(x,y,z) \ - { \ + (struct my_cool_struc) { \ .field_x = (x), \ .field_y = (y), \ .field_z = (z), \ }
方案2:修改赋值语句,添加类型转换
如果不想改动宏定义,也可以在赋值语句里给宏调用的结果加上类型转换:
- p[index++] = MY_COOL_MACRO(a1, a2, a3); + p[index++] = (struct my_cool_struc)MY_COOL_MACRO(a1, a2, a3);
内容的提问来源于stack exchange,提问作者0andriy
相关产品推荐
相关产品推荐

