C找到静态数组大小(防止错误)

ide*_*n42 14 c arrays c-preprocessor

查找静态数组的大小是一种常见操作.看:C找到静态数组大小 -sizeof(a) / sizeof((a)[0])

这可以包装成一个宏,例如:

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

但是它可能会意外地传入常规指针.

例如: void func(SomeArray **foo) { int i = ARRAY_SIZE(foo); }

虽然它的有效C,但往往最终成为一个逻辑错误.

它可以防止这种错误(利用每个处理器在零长度位域上失败).


#define ARRAY_SIZE(a) \
    ((sizeof(struct { int isnt_array : \
     ((const void *)&(a) == &(a)[0]); }) * 0) + \
     (sizeof(a) / sizeof(*(a))))
Run Code Online (Sandbox Code Playgroud)

我发现这个宏适用于GCC,但是对于间接引用的成员,它与Clang失败了.同error: expression is not an integer constant expression

例如:

  • char word[8]; int i = ARRAY_SIZE(word); 好.
  • struct Bar { word[8]; }
    void func(struct Bar *foo) { int i = ARRAY_SIZE(foo->word); } 失败.

有没有更便携的方式来实现这个?(与Clang合作当然很好,虽然我对一般可移植性感兴趣......其他编译器也是如此).

这似乎是一个常见的任务,拥有一个可重复使用的便携式宏是件好事.

chq*_*lie 2

尝试这个:

#define ASSERT_ARRAY(a) \
    sizeof(char[1-2*__builtin_types_compatible_p(__typeof__(a), __typeof__(&(a)[0]))])

#define ARRAY_SIZE(a) \
    (ASSERT_ARRAY(a)*0 + sizeof(a)/sizeof((a)[0]))
Run Code Online (Sandbox Code Playgroud)

它不可移植,但可以与gcc和一起使用clang,并且比 nm 的建议具有更少的副作用。