2014-09-23 82 views
4

我想了解下面的编译错误(使用gcc)背后的原因。C - 初始化后填充struct - 编译错误

0. struct mystruct { 
1.  int x; 
2.  int y; 
3. }; 
4. 
5. int foo() { 
6.  struct mystruct m = {1}; // compiles successfully 
7.  m = {2,3};     // compilation error: expected expression before ‘{’ token 
8.  return m.x + m.y; 
9. } 

但是,如果我在第7行显式转换值,代码编译:

5. int foo() { 
6.  struct mystruct m = {1}; // compiles successfully 
7.  m = (struct mystruct){2,3}; // compiles successfully 
8.  return m.x + m.y; 
9. } 

我想了解这个错误背后的原因。 第6行成功编译而不会引发错误 - 编译器会自动计算出m的类型,而无需进行明确的转换。为什么它在第7行没有这样做?

谢谢

+0

解决为什么它是必要的:编译器应如何知道初始化之外的{2,3}类型?可能是'char [2]'以及'struct {int a,b; }'etc. – mafso 2014-09-23 14:24:24

+0

它可以像第6行一样完成 - 使用'm'类型。 – Oren 2014-09-23 14:50:36

+0

这将与整个语言的其他部分不一致。 C没有类型推断,每个表达式都有一个类型。 “{2,3}”不能是表达式,因为它没有类型。这些规则在允许的地方会非常复杂,并且会使语言不那么强大。例如,你可以使用复合文字来做'void * bar =&(struct mystruct){2,3};'等等。 – mafso 2014-09-23 15:11:45

回答

3

在C中,符号=用于赋值和初始化。前者希望在右侧有一个表达式,大括号内的初始化列表不是。

在你的第二个例子中,你没有处理一个强制转换,而是一个复合文字,一个C99加法。从语义上讲,它相当于

struct mystruct tmp = {2,3}; // initialization 
m = tmp; // assignment 
0

您的第7行(第一个块)在C99中是无效的语法。一项任务需要在其右侧表达,{2,3}而不是的有效表达式。

你的第6行(第一个块)是定义的初始化。

4

原因是C90语法只允许化合物初始化程序

换句话说,在=的右手侧上的支撑的是一个初始化表达,这是不字面的struct类型。

C99增加了compound literals这使它工作。