【问题标题】:Assign to array in struct in c在c中分配给struct中的数组
【发布时间】:2014-02-13 03:13:32
【问题描述】:

我有以下代码:

typedef struct Test {
  long mem[1000];
} Test;

extern Test *test;
int main() {
    Test *test =  (Test *)malloc(sizeof(Test)); 
    test->mem[0] = 1;
    test->mem[1] = 2;
    test->mem[2] = 3;
    test->mem[3] = 4;
    test->mem[4] = 5;
    test->mem[5] = 6;
   return 0;
}

它工作正常,但我想将 mem 数组的初始化更改为这种方式:

test->mem = {1,2,3,4,5,6};

但是 gcc 给了我这个错误:

error: '{' token test->mem = {1,2,3,4,5,6} 之前的预期表达式; 箭头指向左开括号。

它可能是什么?

谢谢!

编辑: 我也试试这段代码:

long mem[1000] = {1,2,3,4,5,6};
    test->mem = mem;

我从 gcc 收到此错误:

错误:分配给类型“long int[1048576]”时的类型不兼容 从 type 'long int *' test->mem = mem;

我不允许使用任何 C 函数。

【问题讨论】:

    标签: c arrays gcc struct


    【解决方案1】:

    数组不是指针(但数组衰减为指针,参见this),并且你不能分配数组(只能初始化它们,或者分配struct- s 包含它们)。您可以复制数组,例如

    Test *test =  (Test *)malloc(sizeof(Test)); 
    if (!test) { perror("malloc"); exit(EXIT_FAILURE); };
    static const int arr[] = {1,2,3,4,5,6};
    memcpy (test->mem, arr, sizeof(arr));
    

    顺便说一句,您可以在不使用 memcpy 的情况下通过编码循环 for (int i=0; i<6; i++) test->mem[i] = arr[i]; 来复制 ....

    这使得test 中的9994 个整数未初始化;你可能想清除它们:

    memset (test->mem+6, 0, 9994*sizeof(int));
    

    或使用另一个for循环。

    您还可以定义您的初始化结构,例如

    Test mystruct = {0, 2, 4, 6, 8};
    

    然后分配它,例如

    *test = mystruct;
    

    但是你不能分配数组!甚至

    // wrong code, won't compile
    int ta[4] = { 0, 1, 2, 3}; // initialization, not assignment
    int tb[4] = { 2, 4, 6, 8}; // ditto
    int *tp = &ta;
    ta = tb; // wrong!
    tb = tp; // also wrong
    

    不会编译。

    FWIW,C++11std::array 提供帮助。

    C11 标准的§6.5.16.1 简单赋值部分(参见n1570 草稿第 102 页)列出了一组关于赋值的约束,而数组赋值不适合在那里。因此是被禁止的。经验法则是,只有标量(包括指针和数字 l-values)或 struct-s 可以出现在赋值的左侧(或者是函数的 return-ed)。

    【讨论】:

    • 对不起,我不明白。为什么 test->mem[0] = 1;工作和测试->mem = {1,2,3,4,5,6};没有?
    • 我看不出“数组不是指针”这句话的相关性。问题中的代码不会尝试将指针用作数组,反之亦然。问题是尝试使用初始化语法进行赋值。
    • @EricPostpischil 我相信它与问题的最新编辑有关。
    • @ValekHalfHeart:编辑尝试将一个数组分配给另一个数组,而不是将数组用作指针,反之亦然。错误消息提到了从数组中生成的指针,但这不是 OP 的意图。
    【解决方案2】:

    something = { initial values } 语法只允许在初始化中使用,其中定义了一个对象,例如:

    long mem[1000] = { 1, 2, 3, 4, 5, 6 };
    

    x = value 等表达式是赋值,不能使用语法进行初始化。

    另一种方法是创建一个您初始化的临时对象,然后将该临时对象的内容复制到目标中:

    static const long temporary[] = { 1, 2, 3, 4, 5, 6 };
    memcpy(test->mem, temporary, sizeof temporary);
    

    关于编辑:

    数组不能赋值;如果x 是一个数组,则x = value 无效。但是,可以分配结构,因此另一种选择是创建一个结构作为临时对象,对其进行初始化并分配:

    // (After the malloc is successful.)
    static const Test temporary = { { 1, 2, 3, 4, 5, 6 } };
    *test = temporary;
    

    但是,请注意,这段代码做了一些之前的代码没有做的事情。我之前展示的示例仅将六个元素复制到数组中。这段代码创建了一个Test 类型的临时对象,其中包含1000 个元素,其中大部分为零,并将所有这些元素复制到*test。即使编译器对此进行了优化并使用一些代码来清除*test,而不是实际复制存储在内存中的零,它也比仅仅复制六个元素需要更长的时间。因此,如果您只想初始化几个元素而不关心其余元素,请使用以前的代码。如果您想要初始化所有元素(大多数为零),您可以使用后面的代码。 (即便如此,我也会考虑替代方案,比如使用calloc 而不是malloc。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-17
      • 2022-01-22
      • 2021-07-30
      相关资源
      最近更新 更多