结构体柔性数组检测及GCC与Clang行为正确性探讨
GCC与Clang柔性数组类型处理差异及兼容宏实现
标准符合性判断
根据C11标准(ISO/IEC 9899:2011)6.7.2.1p18的规定:
- 柔性数组成员的本身类型是不完全数组类型;
- 但当通过
.或->运算符访问柔性数组成员时,其行为会被视为一个足够大的完整数组,此时数组类型不再是不完全类型。
Clang将(struct flexed){0}.m这类访问柔性数组成员的表达式仍视为不完全数组类型,不符合标准中“访问时数组类型非不完全”的要求;而GCC将该表达式视为完整数组类型,更贴近标准文本的规定。
兼容GCC与Clang的检测宏实现
可以利用两款编译器均支持的非标准内置函数__builtin_is_flexible_array_member实现兼容检测。该函数接受指向结构体成员的指针,返回1表示该成员是柔性数组,返回0则不是。
宏定义
#define ISFLEXIBLE(type, member) __builtin_is_flexible_array_member(&((type){0}.member))
测试示例
struct flexed{ int a; char m[]; }; struct unflexed0{ int a; char m[1]; }; struct unflexed1{ int a; char m[1]; int b; }; // GCC与Clang均可通过以下断言 _Static_assert(ISFLEXIBLE(struct flexed,m),""); _Static_assert(!ISFLEXIBLE(struct unflexed0,m),""); _Static_assert(!ISFLEXIBLE(struct unflexed1,m),"");
该宏依赖编译器的非标准特性,但检测逻辑准确,能同时兼容GCC和Clang。
内容的提问来源于stack exchange,提问作者Petr Skocik
相关产品推荐
相关产品推荐

