初始化结构数组初始化单个元素的所有成员,为什么?

时间:2016-08-11 15:29:02

标签: c arrays syntax initialization structure

为什么会有人这样做?更好的是,这甚至如何工作?我会假设这将以某种方式创建一个三个结构的数组,只定义了第一个成员。我意识到一个指针指向数组的第一个元素,我看到它是如何工作的,但是如何定义它会让我失望! (gcc 4.8.4)

void do_something(const void *);

typedef struct{

int a;
char b;
int c;

} the_data_t;

int main(int argc, char *argv[])
{
   the_data_t my_data[] = {10, 'a', 30};
   do_something((const void *)my_data);
}

void do_something(const void *data)
{
   printf("data a: %d\ndata b: %c\ndata c: %d\n", ((the_data_t*)data)->a,
      ((the_data_t*)data)->b, ((the_data_t*)data)->c);
}

输出

  

数据a:10
数据b:a数据c:30

无论如何,我把它改成了..

int main(int argc, char *argv[])
{
   the_data_t my_data = {10, 'a', 30};
   do_something(&my_data);
}

4 个答案:

答案 0 :(得分:8)

  

我原以为这会以某种方式创建一个由三个结构组成的数组,只定义了第一个成员

不,不是那样的。基本上它创建了一个元素的数组,所有成员都是初始化的。

引用C11,章节§6.7.9

  

每个大括号括起的初始化列表都有一个关联的当前对象。什么时候没有   如果存在名称,则按照顺序初始化当前对象的子对象   到当前对象的类型:数组元素增加下标顺序,结构   声明顺序中的成员,以及联合的第一个指定成员。 [...]

  

每个指示符列表都使用与之关联的当前对象开始描述   最接近的周围支撑对。指定符列表中的每个项目(按顺序)指定a   其当前对象的特定成员,并为下一个更改当前对象   指定者(如果有的话)成为该成员。 150)当前对象在结束时产生   指定符列表是由以下初始化程序初始化的子对象。

  

[...]如果是初始化者   subaggregate或包含的联合以左括号开始,初始化器由括号括起   该大括号及其匹配的右大括号初始化元素或成员   subaggregate或包含的联合。否则,列表中只有足够的初始值设定项   考虑到子聚合的元素或成员或者第一个成员   包含的联盟; [...]

基本上,您的代码应该理想看起来像

the_data_t my_data[] = {{10, 'a', 30}}; 

可视化初始化一个元素。

OTOH,你期望的可能是通过

实现的
 the_data_t my_data[] = {{10}, {'a'}, {30}};

它创建一个包含3个元素的数组,所有元素都已初始化成员变量a

那就是说,

 the_data_t my_data[] = {{10, 'a', 30}};

相当于写作

 the_data_t my_data = {10, 'a', 30};

除了部分之外,my_data将不再是一个数组(但是一个元素数组有什么用处,一般来说都是?)。

答案 1 :(得分:3)

编译器会处理

the_data_t my_data[] = {10, 'a', 30};   

as

the_data_t my_data[1] = {{ 10, 'a', 30 }}; // Though it will raise warning.  

因此,my_data是一个the_data_t类型的数组。

这类似于二维数组声明为

int a[][3] = { 1, 2, 3 }; 

然后编译器将其视为

int a[1][3] = { { 1, 2, 3 } }; 

打印a的尺寸,您将获得12(如果该机器上int的尺寸为4。)

答案 2 :(得分:2)

这不合适。 GCC会给你一个警告:

warning: missing braces around initializer
warning: (near initialization for ‘my_data[0]’)

它将做的是创建一个1元素数组。

答案 3 :(得分:2)

如果您使用警告开关,gcc会向您发出有关此问题的警告。

$ gcc -Wall test.c 
test.c: In function ‘main’:
test.c:14:25: warning: missing braces around initializer [-Wmissing-braces]
 the_data_t my_data[] = {10, 'a', 30};
                        ^
test.c:14:25: note: (near initialization for ‘my_data’)
$ 

要解决此问题,您可以将数组正确初始化为:

the_data_t my_data[] = {{10, 'a', 30}};

或者,正如您在帖子中所示,您可以将my_data更改为结构变量。

the_data_t my_data = {10, 'a', 30}; // And call do_something as
do_something((const void *)&my_data);