【问题标题】:How to reinitialize an array in C (not C++)?如何在 C(不是 C++)中重新初始化数组?
【发布时间】:2012-04-04 14:32:15
【问题描述】:

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

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

例如,我将其定义为:

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

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

【问题讨论】:

  • “重新初始化”到底是什么意思?
  • 你的意思是释放旧数组并重新分配?
  • @JerryCoffin 我的意思是重新初始化,一旦我创建了一个数组,然后我想用它的大小和成员重新初始化它

标签: c arrays initialization object-initializers


【解决方案1】:

初始化只发生一次,当你创建数组时:

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]的内容,类似于尝试改变字符串文字的内容是未定义的(虽然我还没有找到章节和诗句在那)。

【讨论】:

    【解决方案2】:

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

    如果您需要为每个数组分配新值,您可以显式循环遍历数组并再次填充它

    使用 memset()memcpy() 将所有元素设置为特定值或分别复制特定元素。

    【讨论】:

    • 运行时在纯 c 中调整数组长度怎么样?以及如何使用 abot free()/realloc() 呢?
    • @user1131997: 数组的长度需要是编译时常量,所以你不能在运行时修改它。另外,你只能使用realloc()调整动态分配的数组的大小,但是那不是重新初始化。
    【解决方案3】:

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

    在您的情况下,您可以在创建数组期间对其进行初始化。下次您分配某个值并不意味着“初始化”;而这只是一个运行时分配。

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

    【讨论】:

    • 在运行时无法在纯 c 中完成数组的重新初始化,或者我使用指针 free()/realloc() ?
    • realloc() 将重新分配一个新的大小。 free() 将清除所有分配的内存。在你的情况下,你可以realloc()
    【解决方案4】:

    我分配新值的部分解决方案(在 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 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-08
      • 1970-01-01
      • 1970-01-01
      • 2011-01-11
      • 2019-09-29
      • 2011-09-08
      • 1970-01-01
      相关资源
      最近更新 更多