Aviv Cohn
Aviv Cohn

Reputation: 17243

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

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?

Upvotes: 9

Views: 7914

Answers (4)

klutt
klutt

Reputation: 31409

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?

Upvotes: 5

Jabberwocky
Jabberwocky

Reputation: 50883

The standard function for this is memset. Theoretically, it's not 100% portable, but in practice it's extremely unlikely that it should cause any real problems and it is widely used.

Instead of

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

you just can use this:

memset(array, 0, array_length * sizeof(array[0]));

The third parameter of memset is the length in bytes of the memory to be set to zero. Therefore ylu need to multiply the array length by the size of one array element which is sizeof(array[0]).

Now it is true that NULL can be something else than a value with all bits set to 0, in such an implementation memset won't work for setting all pointers to NULL. But this is rather theoretic, In the last 30 years I've never seen an implementation where NULL was different from a value with all bits set to 0.

As for your second question:

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?

No, there is no such thing in C, you need to do it with a loop. In C++ you can do stuff like this.

Upvotes: 1

chqrlie
chqrlie

Reputation: 145277

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.

Upvotes: 1

Siddharth
Siddharth

Reputation: 321

I think, this should work.

int *arr[10] = {0}; // arr is array of size 10, where each element is pointer to an int.

This will initialize every element of the array to 0.

This is also guaranteed to work on all the platforms.

Upvotes: 0

Related Questions