The basic idea is to call a function pointer receiving a pointer to an array of the desired type with a pointer to the parameter. As we don't know the base type of the array we can use the commonly provided extension __typeof__
to get it. Then we can use the "normal" ASIZE()
to get its size and a pointer to that type will be defined by
#define GET_COMPATIBLE_ARRAY_PTR_TYPE( a ) __typeof__((a)[0])(*)[ASIZE(a)]
Now we define the type of a function pointer taking that array pointer type as a parameter and returning void:
#define GET_CHECKING_FUNC_PTR_TYPE( a ) void (*)(GET_COMPATIBLE_ARRAY_PTR_TYPE( a ))
We can then cast a NULL
pointer to that function pointer type and call it with a pointer to the argument:
#define CHECK_ARRAY_SEGFAULT( a ) ((GET_CHECKING_FUNC_PTR_TYPE( a ))NULL)(&(a))
That code "works", in the sense of compiling when a is an array and failing to compile otherwise... but it gives us a segmentation fault when executed. We can solve that by using the short-circuiting behavior of boolean operators and adding a cast to void
to avoid compiler warnings:
#define GET_CHECKING_FUNC_PTR_TYPE( a ) (int (*)(GET_COMPATIBLE_ARRAY_PTR_TYPE( a )))
#define CHECK_ARRAY(a) ((void)(0&&((GET_CHECKING_FUNC_PTR_TYPE( a ))NULL)(&(a))))
This version compiles & executes correctly. The presented version is just the (almost) fully substituted version.