Skip to content

Instantly share code, notes, and snippets.

@mchouza
Last active August 29, 2015 14:28
Show Gist options
  • Save mchouza/648dc75a6ced1bcfbf58 to your computer and use it in GitHub Desktop.
Save mchouza/648dc75a6ced1bcfbf58 to your computer and use it in GitHub Desktop.
Explanation of the array type checking

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment