How to reinitialize an array in C (not C++)?

user1131997 picture user1131997 · Mar 20, 2012 · Viewed 26.1k times · Source

How can I reinitialize an array in C?

Should I define it through a pointer: int *data[], or can I just code: int data[] = {};?

For example, I have defined it like:

int main(void) {
    int data[] = {44, 22, 1, 2, 3, 1000, 3};

Now, how do I reinitialize the array data?

Answer

John Bode picture John Bode · Mar 20, 2012

Initialization only occurs once, when you create the array:

int foo[] = {0,1,2,3,4}; // creates a 5-element array of int and
                         // initializes it

Once the array has been defined, you can assign to individual elements:

foo[0] = 5;
foo[1] = 4;
foo[2] = 3;
foo[3] = 2;
foo[4] = 1;

but you cannot assign to the array itself; IOW, you cannot write something like

foo = {5,4,3,2,1};

You can, however, use memcpy to copy the contents of one array to another:

int foo[5];
int bar[5] = {1,2,3,4,5};
int i;

memcpy(foo, bar, sizeof bar); // Copies *contents* of bar to foo

for (i = 0; i < sizeof foo / sizeof *foo; i++)
  printf("foo[%d] = %d\n", i, foo[i]);

Similarly, an array created in this manner cannot be resized; its size is fixed at declaration time. In C89 and earlier, the array size has to be known at compile time - either by specifying the size with a compile-time constant (an integral expression or a macro that expanded to an integral expression) or by using an initializer such as above, from which the array size is computed.

C99 introduced variable length arrays, which can be declared using a run-time value, such as:

void foo(int x)
{
  int arr[x];
  ...
}

Note that, like regular arrays, VLAs cannot be resized after they have been defined.

Alternately, you can dynamically allocate an array using malloc, although you cannot initialize it in the manner above:

int *foo = malloc(sizeof *foo * N); // where N is the number of elements

You can still assign to individual elements:

foo[0] = 5;
foo[1] = 4;
foo[2] = 3;
...

or you can use memcpy as demonstrated above. Note that you must remember to free the array when you're done:

free(foo);

Arrays created in this manner can be resized, using realloc:

int *tmp = realloc(foo, sizeof *foo * NEW_NUMBER_OF_ELEMENTS);
if (tmp)
  foo = tmp;

Why not just assign the result of realloc back to foo? If the realloc operation fails, it will return NULL. If that happens and we assign the result back to foo, we lose track of the memory we've already allocated, leading to a memory leak.

C99 introduced an array literal syntax; you can write something like

int *foo = (int[]){1,2,3,4,5};

and then index into foo like an array:

printf("foo[%d] = %d\n", i, foo[i]);

although I'm pretty sure you cannot alter the contents of foo[i], similar to how attempting to alter the contents of a string literal is undefined (although I haven't found chapter and verse on that).