Quotes of the week
Posted Mar 15, 2007 12:33 UTC (Thu) by
nix (subscriber, #2304)
In reply to:
Quotes of the week by martin@zeroscale.com
Parent article:
Quotes of the week
It's quite nifty.
Breaking it down:
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])
This was the original. It works fine if arr is an array, but if it's a pointer, it'll return rubbish. (This is the one situation in which the decay of arrays to pointers is detectable. Obviously declaring a parameter using the [] syntactic sugar, e.g. char *argv[] doesn't help; it's still a pointer, not an array.)
The rest makes sense if you read it from the inside out (as is so often the case with C, and, for that matter, with bracketed expressions anywhere).
!!__builtin_types_compatible_p(typeof(arr), typeof(&arr[0]))
__builtin_types_compatible_p returns 1 if two types are compatible and 0 otherwise. This compares the type of arr to the type of the address of its first element (guaranteed to be a pointer even if the original was an array). It gets !!ed to ensure that the result is specifically 0 or 1 (GCC guarantees that in the docs right now, but it's easy to envisage a situation in which it returned 0 or some nonzero value. This guards against that happening.)
So now we need to arrange for that 1 value to lead to some sort of compiler warning.
sizeof(typeof(int[1 - 2*!!__builtin_types_compatible_p(typeof(arr), typeof(&arr[0]))])*0)
The bit inside the square brackets yields 1 if the types are incompatible (1 - 2*0) and -1 if it isn't. int[1] is a valid type; int[-1] isn't, and the compiler warns if you try to take its size; and that'll happen if arr is of a type compatible with a pointer (but not if it's an array).
Then the multiplication by zero eliminates any actual non-warning effects of all this code.
(
Log in to post comments)