我试图编写一个宏来检测 struct 成员是灵活数组还是常规array.
事实证明,clang将灵活的数组类型视为不完整(尚未调整大小)的数组类型.
在不同的兼容性测试中,可以通过与不同的特定大小兼容来检测不完整的数组类型:
#define ISCOMPWITHARRAYOFN(LVAL,N) _Generic((typeof((LVAL)[0])(*)[N])0, default:0,typeof(&(LVAL)):1)
#define ISINCOMPLETE_ARRAY(LVAL) ( ISCOMPWITHARRAYOFN(LVAL,1) && ISCOMPWITHARRAYOFN(LVAL,2) )
extern char incomplete[];
extern char complete[1];
//accepted by both gcc and clang
_Static_assert(ISINCOMPLETE_ARRAY(incomplete),"");
_Static_assert(!ISINCOMPLETE_ARRAY(complete),"");
这意味着在叮当作响时,我可以拥有:
#define ISFLEXIBLE(type,member) ISINCOMPLETE_ARRAY((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; };
//both GCC and clang accept these:
_Static_assert(!ISFLEXIBLE(struct unflexed0,m),"");
_Static_assert(!ISFLEXIBLE(struct unflexed1,m),"");
//only clang accepts these
_Static_assert(ISFLEXIBLE(struct flexed,m),"");
_Static_assert(ISCOMPWITHARRAYOFN((struct flexed){0}.m,1),"");
_Static_assert(ISCOMPWITHARRAYOFN((struct flexed){0}.m,2),"");
但GCC并不接受这一点.
我的问题是,GCC中的哪一个在这里表现不正确,能不能写下
一个(可能是非标准的)ISFLEXIBLE(type,array_typed_member)
宏能同时在两个编译器上运行?