如何在C(而不是C ++)中重新初始化数组?

时间:2012-03-20 04:45:08

标签: c arrays initialization object-initializers

如何在C中重新初始化数组?

我应该通过指针定义它:int *data[],还是只需编码:int data[] = {};

例如,我已将其定义为:

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

现在,如何重新初始化数组data

4 个答案:

答案 0 :(得分:11)

初始化仅在创建数组时出现一次:

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

定义数组后,您可以分配给各个元素

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

但你不能分配给数组本身; IOW,你不能写像

这样的东西
foo = {5,4,3,2,1};

但是,您可以使用memcpy将一个数组的内容复制到另一个数组:

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]);

同样,以这种方式创建的数组也无法调整大小;它的大小在申报时固定。在C89及更早版本中,必须在编译时知道数组大小 - 通过使用编译时常量(扩展表达式或扩展为整数表达式的宏)指定大小,或者使用如上所述的初始化程序,从中计算数组大小。

C99引入了可变长度数组,可以使用运行时值声明,例如:

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

请注意,与常规数组一样,VLA在定义后无法调整大小。

或者,您可以使用malloc动态分配数组,但不能以上述方式初始化它:

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

您仍然可以分配到各个元素:

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

或者您可以使用memcpy,如上所示。请注意,完成后必须记住free数组:

free(foo);

使用realloc

以这种方式创建的数组可以调整大小
int *tmp = realloc(foo, sizeof *foo * NEW_NUMBER_OF_ELEMENTS);
if (tmp)
  foo = tmp;

为什么不将realloc的结果分配回foo?如果realloc操作失败,则返回NULL。如果发生这种情况并将结果分配回foo,我们就会忘记已经分配的内存,从而导致内存泄漏。

C99引入了数组文字语法;你可以写点像

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

然后像数组一样索引到foo

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

虽然我很确定你不能改变foo[i]的内容,类似于如何尝试改变字符串文字的内容是未定义的(尽管我还没有找到章节和那节经文)。

答案 1 :(得分:4)

你不能重新初始化任何类型,绝对不是数组 初始化是一次性事件,当您在创建变量时为同一语句中的变量提供某些值。

如果您需要为每个人分配新值,您可以显式循环遍历数组并重新填充它 OR
使用 memset() memcpy() 将所有元素设置为特定值或将特定元素复制到其中。

答案 2 :(得分:1)

初始化(如果有)必须在创建变量期间完成。因为,在编译期间,编译器会将此值分配给变量。此行之后的任何其他分配仅在运行时执行。

在您的情况下,您可以在创建阵列期间初始化阵列。下次分配某个值时,并不意味着初始化&#39 ;;相反,它只是一个运行时分配。

如果要动态创建和存储元素,则可以使用指针来执行此操作。

答案 3 :(得分:1)

我分配新值的部分解决方案(适用于 gcc 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++; }

它不安全(没有边界检查),从头开始只覆盖连续的成员,但我觉得它有时很有用。

完整示例:

#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);
}

输出:

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