Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C find static array size (preventing mistakes) [duplicate]

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.

like image 378
ideasman42 Avatar asked Apr 28 '15 16:04

ideasman42


People also ask

How do you determine the size of an array that is static?

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]);

Can a static array have a variable size?

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).

Why does the GROW Method double the size of the array instead of just increase it by one cell?

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".

Can you modify a static array?

Statically declared arrays are allocated memory at compile time and their size is fixed, i.e., cannot be changed later.


1 Answers

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.

like image 184
chqrlie Avatar answered Sep 30 '22 15:09

chqrlie