c - 对于结构变量,为什么初始化器{21,19,3.6}与{{21,19},3.6}相同,反之则不然?

标签 c arrays structure curly-braces braces

在下面的示例中,我使用两个结构 test1test2 对此进行了说明。第一个有两个元素 - 一个大小为 2 的整数数组和一个浮点元素.第二个结构有3个元素,2个整数和1个 float 。

我将 test1 的两个结构变量 s1s2 初始化为:

s1={{23,52},2.5},s2={21,19,3.6};

即使对于 s2 我已经取出了包含数组元素的大括号,但两者都工作正常。它在没有警告的情况下工作正常并且输出是正确的。但是当我为 test2 初始化 2 个变量时如下:

 v1={{23,52},2.5},v2={21,19,3.6};

当我尝试打印出 v1 的值时,我得到了错误的输出,这些是我在编译时收到的警告:

warning: braces around scalar initializer|
warning: (near initialization for 'v1.list1')|
warning: excess elements in scalar initializer|
warning: (near initialization for 'v1.list1')|
||=== Build finished: 0 errors, 4 warnings ===|

基于此前提,请澄清以下产生的疑问:

问题:如果使用 v1={{23,52},2.5} 而不是 v1={23,52,2.5}使编译器混淆前 2 个数字是结构的不同整数元素还是结构的整数数组元素的一部分,那么为什么不使用 s2={21,19,3.6} 代替s2={{21,19},3.6} 使编译器误以为结构 varialbe s23 个元素(2 个整数元素和一个 float ),而不是 2 元素(一个大小为 2 的整数数组和一个 float )?我特别想了解的是,为什么第一种情况是关于 v1' s 初始化错误。

#include<stdio.h>

struct test1{
int list[2];
float rate;
}s1={{23,52},2.5},s2={21,19,3.6}; //Works fine

struct test2{
int list1;
int list2;
float rate;
}v1={{23,52},2.5},v2={21,19,3.6};  //Messes things up

int main(void)
{
    printf("%d,%d,%f\n",s1.list[1],s2.list[1],s2.rate);
    printf("%d,%d,%f\n",v1.list1,v1.list2,v1.rate);
}

最佳答案

这只是初始化程序规则定义方式的结果。如果初始化的当前对象structunion 或数组,那么如果下一个初始化程序以{ 然后由该大括号括起来的初始化器及其匹配的 } 用于初始化该对象的成员;否则,它只是遍历初始化器列表,需要多少就取多少。

因此,在第一种情况下 s1={{23,52},2.5},当前对象以 s1.list 开头。这是一个数组,下一个初始化程序是 { 23, 52 } ,因此它用于初始化数组。 s1.rate 现在是当前对象,下一个初始化器是 2.5,所以它按预期工作。

在第二种情况 s2={21,19,3.6} 中,当前对象以 s2.list 开头。这是一个数组,但下一个初始化器不是{ 开始 - 所以它根据需要获取尽可能多的值(在本例中为两个),并初始化包含 2119 的数组。 s2.rate 现在是当前对象,下一个初始化器是 2.5,所以再次按预期工作。

在第三种情况 v1={{23,52},2.5} 中,当前对象以 v1.list1 开头。这是一个标量,对应的初始化器是{23, 52}。这违反了语言的约束——“标量的初始值设定项应该是单个表达式,可以选择用大括号括起来”——所以这就是你收到警告的原因。形式上你的程序的行为是未定义的,但看起来你的编译器只使用初始化程序中包含的第一个值并丢弃多余的值。当前对象现在是 v1.list2,下一个初始化器是 2.5,因此使用了错误的值来初始化该成员。 v1.rate 没有初始化器;由于 v1 具有静态存储持续时间,因此该成员初始化为 0.0

在第四种情况 v2={21,19,3.6} 中,当前对象以 v1.list1 开始,下一个初始化程序是 21 - 此值用于初始化成员。在此之后,当前对象是 v1.list2,下一个初始化程序是 19;然后 v1.rate 是当前对象,下一个初始化器是 3.6

为了尽量减少混淆,您应该始终为每个 struct 或数组子对象使用大括号括起来的初始化程序。

关于c - 对于结构变量,为什么初始化器{21,19,3.6}与{{21,19},3.6}相同,反之则不然?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16514806/

相关文章:

javascript - 如何将文本从 DIV 数组添加到 DIV

php - 为什么我会收到此数组到字符串转换错误?

c - union 作为 C 中的结构变量

c - 使用 do-while 搜索结构中的元素

不带括号的C函数调用

c - 访问全局整数数组时出现段错误

c - struct "sockaddr_in servaddr, clientaddr;"是什么意思?

arrays - 有什么直接的方法可以在 Perl 数组上应用逻辑运算符?

c - 指向函数的指针如何在 C 中发挥作用?

c - 在 gcc 编译器之前构建 binutils