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