2017-05-26 46 views
1

我有以下結構類型:初始化匿名結構的,解決方法GCC 4.9

typedef struct PG_Point PG_Point; 
struct PG_Point 
{ 
    int x; 
    int y; 
}; 

typedef struct PG_Size PG_Size; 
struct PG_Size 
{ 
    int width; 
    int height; 
}; 

typedef struct PG_Bounds PG_Bounds; 
struct PG_Bounds 
{ 
    union 
    { 
     struct 
     { 
      PG_Point topLeft; 
      PG_Size size; 
     }; 
     struct 
     { 
      struct 
      { 
       int x; 
       int y; 
      }; 
      struct 
      { 
       int width; 
       int height; 
      }; 
     }; 
    }; 
}; 

有以下初始化:

#define PG_Point_init(ix, iy) {.x=(ix), .y=(iy)} 
#define PG_Size_init(iwidth, iheight) {.width=(iwidth), .height=(iheight)} 

#define PG_Bounds_init(ix, iy, iwidth, iheight) { \ 
    .topLeft=PG_Point_init((ix),(iy)), \ 
    .size=PG_Size_init((iwidth),(iheight)) } 

據我瞭解,這是正確的初始化匿名結構的字段,就好像它們是包含結構的直接字段一樣?但是用gcc 4.9.2,這給出了以下警告:

警告:缺少初始值設定的領域 '大小' '結構<匿名>'[-Wmissing場-初始化]

它如果我將初始化程序更改爲此版本,則可行:

#define PG_Bounds_init(ix, iy, iwidth, iheight) {{{ \ 
    .topLeft=PG_Point_init((ix),(iy)), \ 
    .size=PG_Size_init((iwidth),(iheight)) }}} 

也就是說,顯式地使用union和struct作爲子聚合。

這甚至允許嗎?我是否期望其他編譯器拒絕這個?

+0

試着用'-pedantic'編譯。如果它不給你警告,你應該很好去。 –

+0

是的,我已經做到了,鏗鏘聲3.5.0和gcc 6.3.0沒有什麼可抱怨的。仍然不確定在閱讀[本答案]的標準報價後是否允許它(https://stackoverflow.com/a/5065829/2371524) –

+1

編譯器沒有拒絕它 - 它只發出警告。你應該認真對待,但這可能不成問題。如何編寫一個簡短的測試程序來檢查對象是否按照預期初始化? –

回答

2

從我的理解,在c11中正確地初始化匿名結構的字段就好像它們是直接包含結構的字段一樣嗎?

這有兩個部分。首先,我們需要解決的是否有這樣的會員可以在所有被初始化的問題,因爲識別匿名結構和工會會員爲特定類型的「無名成員」,並paragraph 6.7.9/9

除非明確說明否則,就本小節而言,結構體和聯合體類型的未命名成員不參與初始化。

節6.7.9的其餘部分(初始化)無處說什麼,我會解釋爲明確應用於匿名結構和匿名工會成員自己,但我不認爲其目的是爲了防止初始化名爲匿名成員的成員,尤其是考慮到他們被認爲是包含結構或聯盟的成員(見下文)。因此,我不解釋標準禁止您嘗試執行的初始化。

所以,是的,我讀了C11以允許您的初始值設定項並指定它具有您想要的效果。特別是,該標準的paragraph 6.7.2.1/13部分說明了

匿名結構或聯合的成員被認爲是包含結構或聯合的成員。如果包含結構或聯合也是匿名的,則這將遞歸應用。因此

你初始化滿足約束在paragraph 6.7.9/7,即內部的代號指定當前對象的成員的名稱(在你的情況下,struct PG_Bounds)。 6.7節的以下段落。9提供了初始化器的語義,並且我沒有理由將它們解釋爲指定除了用您提供的值初始化整個對象之外的任何東西。

在這一點上,我重申,海灣合作委員會發布警告,不拒絕你的代碼,在這種情況下,我認爲警告是虛假的。我寫了一個測試程序,例如我在評論中建議的那樣,並且在C11模式下在gcc 4.8.5上嘗試了它。儘管gcc發出的警告與您提出的警告相同(但僅限於啓用-Wextra),但我能夠證明您的初始化程序已將主題struct PG_Bounds的所有成員初始化爲預期值。


如果你改變了初始化到使用嵌套括號括起初始化一個版本還觀察到,GCC不會發出警告,並要求

這甚至允許嗎?我是否期望其他編譯器拒絕這個?

對於段落6.7.9/9,這可能會被視爲更成問題,所以從這個意義上講,它可能更危險。我不確定是否有任何編譯器實際上拒絕它或者用它做了錯誤的事情。我認爲標準的意圖是允許這個初始化器,但我更喜歡另一種形式,我自己。

+0

我確認約翰的觀點,顯然這個標準的意圖是讓匿名'struct'的字段像直接指定那樣工作。 '-Wextra'通常具有虛假的警告,特別是關於'struct'字段的非初始化。 'struct'成員的默認初始化是C標準的一個重要特徵,並且警告它只是反作用。 –