对于struct变量s1,s2,为什么我可以初始化“s1 = {25,3.5}”,将s2指定为“s1 = s2”,但是不能使用“s1 = {59,3.14}?

在C中,如果它们属于同一类型,我们可以将一个结构变量的值赋值给另一个。根据这个,在我的下一个程序中,当两者都是相同类型的struct变量时,我可以使用s1=s2 。但为什么之后我不允许使用s1={59,3.14}

我知道我们不能将字符串"Test"分配给字符数组arr而不是初始化语句,因为对于字符串"Test" ,它在赋值期间分解为char*类型,因此存在类型不匹配错误。但是我的程序{59,3.14}不会分解为任何指针,是吗?为什么然后它不允许被分配给s1即使它是相同的类型,特别是因为在初始化期间允许它?什么是在s2{59,3.14}之间有所不同,以便允许一个被分配给s1而另一个不被分配给s1

 #include int main(void) { struct test1 { int a; float b; } s1= {25,3.5},s2= {38,9.25}; printf("%d,%f\n",s1.a,s1.b); s1=s2; // Successful printf("%d,%f\n",s1.a,s1.b); s1= {59,3.14}; //ERROR:expected expression before '{' token| printf("%d,%f\n",s1.a,s1.b); } 

C语法严格区分赋值和初始化。

对于初始化,很明显右侧的类型应该是什么:声明的对象的类型。 所以初始化符号是明确的; { a, b, c }是声明顺序中的字段。

对于任务,事情不太清楚。 赋值表达式X = Y首先计算子表达式( XY ),查看它们的类型,然后在可能的情况下,从Y的类型到X的类型进行必要的转换。 forms{ a, b, c }的表达式没有类型,因此该机制不起作用。

yoones在他的答案中使用的构造是另一种动物,称为复合文字。 这是一种创建指定类型的未命名辅助对象的方法。 您可以在初始化或任何其他您想要使用临时对象的地方使用它。 复合文字的存储类和生命周期是从使用它的上下文推导出来的。 如果它在函数范围内,则它是自动的(在“堆栈”上),因为它将是在同一块中声明的普通变量,只是它没有名称。 如果它在文件范围中使用(例如,“全局”变量的初始化)具有静态存储持续时间,并且生命周期是程序执行的整个持续时间。

你需要这样投: s1 = (struct test1){59, 3.14}; 让编译器知道它应该考虑你的{…}类型struct test1。

换句话说,您在括号之间收集的数据没有类型,这就是您需要使用强制转换指定一个类型的原因。

编辑:

编译器需要知道每个结构域的预期类型。 这需要知道每个参数的正确字节数,填充等。否则它也可以将值59(这意味着是一个int)复制为char,因为它是一个适合一个字节的值。