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

4

16

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?

Defend answered 20/3, 2012 at 4:45 Comment(3)
What exactly do you mean by "reinitialize"?Barroom
Do you mean free the old array and reallocate?Periwinkle
@JerryCoffin I meant exactly reinitializing, once I have created an array , then I want to reinitialize it with its size and membersDefend
E
18

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

Exaggerated answered 20/3, 2012 at 12:54 Comment(0)
G
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.

Guillotine answered 20/3, 2012 at 4:48 Comment(2)
How about the reszing array length in pure c in runtime? And how abot free()/realloc() it?Defend
@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.Guillotine
B
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.

Burschenschaft answered 20/3, 2012 at 4:53 Comment(2)
reinitialization of array can't be done in pure c in runtime or I muse use pointer, free()/realloc() ?Defend
realloc() will reallocate with a new size. free() will clear all allocated memory. In your case, you can realloc()Burschenschaft
R
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 
Ramtil answered 19/10, 2015 at 14:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.