This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: Using array_length macro outside function
On 2/4/19 6:34 AM, Florian Weimer wrote:
> +#define array_length(var) \
> + (sizeof (var) / sizeof ((var)[0]) \
> + + 0 * sizeof (struct { int ARGUMENT_NOT_AN_ARRAY: \
> + 1 - (__builtin_types_compatible_p \
> + (__typeof (var), __typeof (&(var)[0]))); }))
In Gnulib apps we've needed static assertions in expressions so often
that we have a macro 'verify_expr (R, E)' that means "verify R
statically, and yield the value of E". With this macro, you could
rewrite the above definition as:
#define array_length(var) \
verify_expr (!__builtin_types_compatible_p (__typeof (var), \
__typeof (&(var)[0])), \
sizeof (var) / sizeof ((var)[0]))
which is quite a bit easier to follow. So I suggest appending something
like the following to include/verify.h:
#define verify_expr(r, e) \
(sizeof (struct { _Static_assert (r, #r); char __dummy; }) \
? (e) : (e))
Then we can have array_length.h include verify.h and use the
abovementioned simpler array_length.
(The Gnulib verify_expr caters to non-GNU and pre-C99 compilers and so
is more complicated, but we don't need that complexity in glibc.)