Finding the size of a static array is a common operation. see: C find static array size - sizeof(a) / sizeof((a)[0])
This can be wrapped into a macro, eg:
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
however its possible to accidentally pass in a regular pointer.
eg: void func(SomeArray **foo) { int i = ARRAY_SIZE(foo); }
While its valid C, but often ends up being a logical error.
Its possible to prevent this mistake (taking advantage of per-processor to fail on a zero length bit-field).
#define ARRAY_SIZE(a) \
((sizeof(struct { int isnt_array : \
((const void *)&(a) == &(a)[0]); }) * 0) + \
(sizeof(a) / sizeof(*(a))))
I've found this macro works with GCC, but fails with Clang, for indirectly referenced members. with error: expression is not an integer constant expression
eg:
char word[8]; int i = ARRAY_SIZE(word);
ok.struct Bar { word[8]; }
void func(struct Bar *foo) { int i = ARRAY_SIZE(foo->word); }
fails.Is there a more portable way to to implement this? (working with Clang is good of course though Im interested in general portability... other compilers too).
This seems such a common task that it would be good to have a re-usable portable macro.
We can find the size of an array using the sizeof() operator as shown: // Finds size of arr[] and stores in 'size' int size = sizeof(arr)/sizeof(arr[0]);
You cannot declare a static array of variable size because its space is allocated in the Data Segment (or bss segment in case of an uninitialized variable).
If you grow the array one element at a time, you end up with quadratic behaviour as you copy the elements from array to array+1 to array+2. Doubling reduces the cost to linear time. This growth strategy gives you get so-called "amortized constant time insertions".
Statically declared arrays are allocated memory at compile time and their size is fixed, i.e., cannot be changed later.
Try this:
#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]))
It is not portable, but works with both gcc
and clang
and has fewer side effects than n.m.'s proposal.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With