2014-09-23 45 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這使它工作。