14

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?

Gaurang Tandon
  • 6,504
  • 11
  • 47
  • 84

4 Answers4

16

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).

John Bode
  • 119,563
  • 19
  • 122
  • 198
4

You cannot re-initialize any types as such, definitely not arrays.
Initialization is a one time event, when you provide some value to a variable in the same statement when it is being created.

You could explicitly loop through array and fill it up again if you need to assign new values to each of them
OR
Use memset() or memcpy() for setting all elements to specific value or copying specific elements to it resp.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • How about the reszing array length in pure c in runtime? And how abot free()/realloc() it? –  Mar 20 '12 at 04:58
  • 1
    @user1131997: The length of an array needs to be a compile time constant, So you cannot modify it at run-time.Also, You can resize only an dynamically allocated array by using `realloc()` but that is not re-initialization. – Alok Save Mar 20 '12 at 05:00
1

My partial solution for assigning new values (works in gcc with c99-syntax):

#define arr_set(type, arr, ...) { \
    int arr_size = sizeof((type[]){__VA_ARGS__}) / sizeof(type); \
    type *parr = (type[]){__VA_ARGS__}; \
    for (int i = 0; i < arr_size; i++) \
        arr[i] = *parr++; }

It's not safe (no bounds checking), overwrites only consecutive members starting from the beginning but I find it useful sometimes.

Complete example:

#include <stdio.h>

#define arr_set(type, arr, ...) { \
    int arr_size = sizeof((type[]){__VA_ARGS__}) / sizeof(type); \
    type *parr = (type[]){__VA_ARGS__}; \
    for (int i = 0; i < arr_size; i++) \
        arr[i] = *parr++; }

#define print_buf_int(buf) { \
    for (int i = 0; i < sizeof(buf)/sizeof(buf[0]); i++) \
        printf("%d ", (int)buf[i]); \
    printf("\n"); }

#define print_buf_char(buf) { \
    for (int i = 0; i < sizeof(buf)/sizeof(buf[0]); i++) \
        if (buf[i]) \
            printf("%c ", (char)buf[i]); \
        else \
            printf("null "); \
    printf("\n"); }

#define print_buf_str(buf) { \
    for (int i = 0; i < sizeof(buf)/sizeof(buf[0]); i++) \
        printf("%s ", (char*)buf[i]); \
    printf("\n"); }

int main()
{
    int brr[8] = {};
    int arr[8] = {3, 4, 5, 1, 0, 2};
    print_buf_int(arr);

    arr_set(int, arr, 9, 8 ,7);
    print_buf_int(arr);

    arr_set(int, arr, 0, 1, 2, 3, 4, 5, 6, 7);
    print_buf_int(arr);

    arr_set(int, arr, 11, 22, 33, 44, 55, 66, 77, 88, 99);  // 'brr' gets overwritten!!!
    print_buf_int(arr);
    print_buf_int(brr);

    unsigned char crr[13] = {'a', 'b', 'c', [12] = 'z'};
    print_buf_char(crr);

    arr_set(char, crr, 'd', 'e', 'f', '1', '2', '3');
    print_buf_char(crr);

    unsigned short srr[] = {111, 222, 333, 444, 555};
    print_buf_int(srr);

    arr_set(unsigned short, srr, -1, 0, 666);
    print_buf_int(srr);

    char *prr[] = {"hello", "variadic", "world"};
    print_buf_str(prr);

    arr_set(char*, prr, "good", "bye");
    print_buf_str(prr);
}

Output:

3 4 5 1 0 2 0 0 
9 8 7 1 0 2 0 0 
0 1 2 3 4 5 6 7 
11 22 33 44 55 66 77 88 
99 0 0 0 0 0 0 0 
a b c null null null null null null null null null z 
d e f 1 2 3 null null null null null null z 
111 222 333 444 555 
65535 0 666 444 555 
hello variadic world 
good bye world 
LennyB
  • 359
  • 1
  • 5
  • 14
1

Initialization (if any) must be done during the time of creating a variable. Because, during the compile time, the compiler assigns this value to the variable. Any other assignments after this line is executed during run-time only.

In your case, you can initialize an array during it's creation. The next time you are assigning some value doesn't mean an 'initialization'; rather it's a run-time assignment only.

If you want to create, and store elements dynamically, then you can use pointers to do so.

Vishnu Haridas
  • 7,355
  • 3
  • 28
  • 43
  • reinitialization of array can't be done in pure c in runtime or I muse use pointer, free()/realloc() ? –  Mar 20 '12 at 04:59
  • 1
    `realloc()` will reallocate with a new size. `free()` will clear all allocated memory. In your case, you can `realloc()` – Vishnu Haridas Mar 20 '12 at 05:09