Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the standard way to set an array of pointers to NULL?

Tags:

arrays

c

Please consider a heap-allocated array of pointers like this:

Thing** array = malloc(sizeof(Thing*) * array_length);

How can I set all of its members to NULL?

I can of course do this:

for (int i = 0; i < array_length; i++) {
    array[i] = NULL;
}

But I'm wondering if there's a standard function for this.

SO mainly mentions memset, however I'm not sure it is guaranteed to work on all platforms for this usecase, since as far as I understand it walks the array byte by byte, and not element by element.

Also more generally, what is the standard way to set all values in an array of any type T, which can be of any size, to some particular value?

like image 314
Aviv Cohn Avatar asked Nov 22 '19 10:11

Aviv Cohn


2 Answers

Your method is fine

I cannot think of any better way to to this than what you already are doing. It's short and clear. It's absolutely nothing wrong with it, and I would not even consider something else.

If it is to save a few lines you can use one of these:

  • for (size_t i = 0; i < array_length; i++) // No braces
        array[i] = NULL;
    
  • for (size_t i = 0; i < array_length; i++) array[i] = NULL; // Single

  • for (size_t i = 0; i < array_length; i++) { array[i] = NULL; } // With braces

But I want to point out that some people have strong opinions about this. I often skip braces for single statement loops. If you use any of these techniques, be prepared for complaints.

Unsafe alternatives

You could use memset, and it will work most of the times. However, the C standard does not require null pointers to be all zeros. Granted, the risk of a failure because of this is minuscule, but why take the risk when the gain is nearly zero? If you ask me, a loop is clearer, because your goal IS to set the pointers to NULL. The loop clearly communicates this.

There are historical examples with non-zero NULL machines: When was the NULL macro not 0?

However, do note that even though NULL is not required to be all zero bits, it IS guaranteed to evaluate to false when used in a Boolean expression. So you can safely use if(!ptr) to check if a call to malloc succeeded or not. I explained it in this answer Is NULL always false?

like image 51
klutt Avatar answered Oct 21 '22 22:10

klutt


Initializing the array with an explicit loop is the only standard conformant approach that is guaranteed to work correctly on all platforms. Good compilers should be able to convert the loop into whatever is more efficient on the target platform for zero initialization if indeed null pointers are represented with all bits zero there.

If you can assume that all-bits zero is a correct representation of null pointers, which is almost always the case but not guaranteed by the C Standard, you can use a call to memset or more efficiently, allocate the array with calloc():

Thing **array = calloc(array_length, sizeof(*array)); // initialize to all bits zero

This can be more efficient than both the call to memset and the explicit loop as calloc() may in some cases assume the memory it gets from the OS to already be zero initialized, as is the case of newly mapped blocks for security reasons.

like image 41
chqrlie Avatar answered Oct 22 '22 00:10

chqrlie