在 C 语言中给结构体中的数组赋值

12

我有以下代码:

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给我报错:

错误: 在左大括号标记之前缺少表达式 test->mem = {1,2,3,4,5,6}; 左箭头指向左括号。

这是什么问题呢?

谢谢!

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

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

我从gcc得到这个错误:

error: 将'type 'long int *'的值赋给类型为'long int[1048576]'的变量'test->mem'时出现不兼容的类型 test->mem = mem;

我不能使用任何C函数。

2个回答

14

语法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。)

2

数组不是指针(但数组会衰变为指针,请参见this),你不能分配数组(只能初始化它们,或者分配包含它们的struct)。你可以复制数组,例如:

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

顺便说一下,你可以通过编写循环for (int i=0; i<6; i++) test->mem[i] = arr[i];而不使用memcpy来进行复制....

这将使test中剩下9994个整数未初始化;您可能需要清除它们:

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

或者使用另一个for循环。

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

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

然后分配它,例如:
*test = mystruct;

但是你不能分配数组!甚至 < / p>
// 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

无法编译。

值得一提的是,C++11 提供了 std::array 来帮助解决这个问题。

C11 标准的 §6.5.16.1 简单赋值 部分(见 n1570 草案第102页)列出了一组关于赋值的限制条件,而数组赋值不符合其中任何一条。因此被禁止。一个经验法则是只有标量(包括指针和数字 l-values)或 struct 可以出现在赋值的左侧(或从函数中返回)。


抱歉,我不明白。为什么 test->mem[0] = 1; 能工作而 test->mem = {1,2,3,4,5,6}; 不行? - Nir
1
我没有看到“数组不是指针”这个语句的相关性。问题中的代码并没有试图将指针用作数组,反之亦然。问题在于尝试使用初始化语法进行赋值。 - Eric Postpischil
1
@EricPostpischil 我认为这与问题的最新编辑有关。 - ApproachingDarknessFish
@ValekHalfHeart:这个编辑尝试将一个数组分配给另一个数组,而不是将一个数组用作指针或反之亦然。错误消息提到了从数组产生的指针,但这不是OP的意图。 - Eric Postpischil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接