对于结构变量s1,s2,为啥我可以初始化“s1 = 25,3.5”,将s2分配为“s1 = s2”,但不能使用“s1 = 59,3.14?
Posted
技术标签:
【中文标题】对于结构变量s1,s2,为啥我可以初始化“s1 = 25,3.5”,将s2分配为“s1 = s2”,但不能使用“s1 = 59,3.14?【英文标题】:For struct variables s1,s2,why can I initialize "s1=25,3.5",assign s2 as "s1=s2",but then can't use "s1=59,3.14?对于结构变量s1,s2,为什么我可以初始化“s1 = 25,3.5”,将s2分配为“s1 = s2”,但不能使用“s1 = 59,3.14? 【发布时间】:2013-05-12 22:00:37 【问题描述】:在C语言中,如果一个结构变量的类型相同,我们可以将它们的值分配给另一个。根据这一点,在我的以下程序中,当两者都是struct
变量时,我可以使用s1=s2
相同类型的。但是为什么在那之后我不允许使用s1=59,3.14
?
我知道除了在初始化语句中之外,我们不能将字符串 "Test"
分配给字符数组 arr
,因为对于字符串 "Test"
,它在分配期间分解为类型 char*
,因此存在类型不匹配错误。但是在我的程序中,59,3.14
不会分解为任何指针,是吗?为什么即使它是同一类型,也不允许将其分配给 s1
,尤其是因为它在初始化?s2
和59,3.14
之间有什么区别,允许将一个分配给s1
,而另一个则不允许?
#include<stdio.h>
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);
【问题讨论】:
最简单的答案(我并不是轻率):因为这就是语法的定义方式。 C99 引入了复合字面量,不知道现在能不能照你说的做。 虽然 yoones 的回答告诉我如何让它在我的代码中工作,但我仍然觉得需要一些解释,一些技术解释关于这里发生了什么。非常欢迎详细回答。 【参考方案1】:C 语法严格区分赋值和初始化。
对于初始化,右边的类型应该是什么很清楚:声明的对象的类型。所以初始化符号是明确的; a, b, c
是声明顺序的字段。
对于分配,事情不太清楚。赋值表达式X = Y
首先计算两个子表达式(X
和Y
),查看它们的类型,然后进行必要的转换,如果可能的话,从Y
的类型到X
的类型。 a, b, c
形式的表达式没有类型,因此该机制不起作用。
yoones 在他的回答中使用的构造是另一种动物,称为复合文字。这是一种创建指定类型的未命名辅助对象的方法。您可以在初始化或您想要使用临时对象的任何其他地方使用它。复合文字的存储类和生命周期是从使用它的上下文中推断出来的。如果它在函数范围内,它是自动的(在“堆栈”上),就像在同一个块中声明的普通变量一样,只是它没有名称。如果它在文件范围内使用(例如,“全局”变量的初始化)具有静态存储持续时间和生命周期,即程序执行的整个持续时间。
【讨论】:
很高兴您提供了一个很好的答案。您能否进一步澄清You may use it in initializations or any other place where you'd want to use a temporary object.
的意思?我的意思是,如果我使用(struct test1)a,b,c
,那么如果它不是临时的,那么复合文字存储在哪里?在数据段中?【参考方案2】:
你需要这样转换它:s1 = (struct test1)59, 3.14;
让编译器知道它应该考虑你的 ... 类型的 struct test1。
换句话说,您在括号中收集的数据没有类型,这就是为什么您需要使用强制转换来指定一个类型。
编辑:
编译器需要知道每个结构字段的预期类型。这需要知道每个参数、填充等的正确字节数。否则它也可以将值 59(这意味着是一个 int)复制为一个 char,因为它是一个适合一个字节的值。
【讨论】:
它有效,但我不知道为什么会这样。对我来说完全陌生。你能解释一下吗? 现在清楚了吗?或者,也许您可以尝试更具体地回答您的问题以帮助我回答。 那不是演员表;它是一个复合文字。 @Thokchom:如果你只写59, 3.14
,编译器不知道那是什么——它只是一些数字,编译器不知道它应该是哪个结构或其他对象.当您编写(MyType) 59, 3.14
时,它会告诉编译器这是MyType
的数据。当59, 3.14
出现在定义中时,编译器已经知道类型,因为它是声明的一部分。 (另外,这是一个初始化器,而不是复合文字,您可以在其中使用一些额外的功能,但这是另一回事。)以上是关于对于结构变量s1,s2,为啥我可以初始化“s1 = 25,3.5”,将s2分配为“s1 = s2”,但不能使用“s1 = 59,3.14?的主要内容,如果未能解决你的问题,请参考以下文章