Linux内核使用了一个很好的ARRAY_SIZE
实现来解决这个问题:
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
具有
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
和
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
Of course this is portable only in GNU C as it makes use of two instrinsics:
typeof
operator 和 __builtin_types_compatible_p
function. Also it uses their "famous" BUILD_BUG_ON_ZERO
macro which is only valid in GNU C.
假设有编译时求值要求(这正是我们想要的),我不知道这个宏的任何可移植实现.
A "semi-portable" implementation (和 which would not cover all cases) is:
#define ARRAY_SIZE(arr) \
(sizeof(arr) / sizeof((arr)[0]) + STATIC_EXP(IS_ARRAY(arr)))
具有
#define IS_ARRAY(arr) ((void*)&(arr) == &(arr)[0])
#define STATIC_EXP(e) \
(0 * sizeof (struct { int ARRAY_SIZE_FAILED:(2 * (e) - 1);}))
With gcc
this gives no warning if argument is an array in -std=c99 -Wall
but -pedantic
would gives a warning. The reason is IS_ARRAY
expression is not an integer constant expression (cast to pointer types 和 subscript operator are not allowed in integer constant expressions) 和 the bit-field width in STATIC_EXP
requires an integer constant expression.