I would like to write a generic function to detect if an array of pointers to some arbitrary type contains a NULL
. My initial attempt was something along these lines:
bool find_null (void *ptrs, size_t num_ptrs) {
void **array = ptrs;
size_t i;
for (i = 0; i < num_ptrs; ++i) {
if (array[i] == NULL) return true;
}
return false;
}
It was pointed out that this could cause a strict aliasing violation, since the array of pointers to Foo
would be accessed as array of pointers to void
, which is not listed as one of the allowed ways an object is allowed to be accessed in C.2011 §6.5¶7.
I could rewrite the function to access the array of pointers as unsigned char *
instead, but I am not sure how to perform the NULL
check without breaking strict aliasing. Can someone provide a valid technique?
bool find_null (void *ptrs, size_t num_ptrs) {
unsigned char *array = ptrs;
void *p;
size_t i;
for (i = 0; i < num_ptrs; ++i) {
memcpy(&p, array + i * sizeof(p), sizeof(p));
if (p == NULL) return true;
/*
* Above seems to still break strict aliasing.
* What should be done instead?
*/
}
return false;
}
The goal is to write a generic function that would work the same as a type specific function. In other words, a generic version of the function below:
bool find_null_Foo (Foo *array[], size_t num_ptrs) {
size_t i;
for (i = 0; i < num_ptrs; ++i) {
if (array[i] == NULL) return true;
}
return false;
}
You cannot do it with the specific interface you present, but you may be able to do it in this somewhat clunky way:
bool find_null (const void *array, size_t num_ptrs, size_t ptr_size,
const void *null) {
const char (*ptr_array)[ptr_size] = array;
size_t i;
for (i = 0; i < num_ptrs; ++i) {
if (!memcmp(array[i], null, ptr_size)) return true;
}
return false;
}
You would call that like so:
struct Foo;
#define ARRAY_SIZE 53
int main(void) {
struct Foo *my_array[ARRAY_SIZE] = { ... };
struct Foo * const foo_null = (struct Foo *) 0;
if (find_null(my_array, ARRAY_SIZE, sizeof(*my_array), &foo_null)) {
puts("It contains NULL");
} else {
puts("It does not contain NULL");
}
}
Do note that that assumes that there is only one representation for null pointers of the type in question, which is true in many implementations, but is not required by the language.
Note also that that isn't actually specific to looking for null pointers, so in fact you can use it to search your pointer array for any pointer value. In fact, it isn't even specific to arrays of pointers -- you can use it to search any array for any value, as long as byte-for-byte equality is a suitable matching criterion (which it isn't for structs or unions, and might not be for some other types).
Additionally, if that suits you then you could probably devise a wrapper macro that makes it a bit easier to use for some of your more common scenarios.