Reputation: 17243
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
Reputation: 31409
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.
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
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
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
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