2012-11-14 410 views
8

我發現如下所示的類似實施演示一個代碼..C中匿名結構/聯合的優點是什麼?

struct st 
{ 
int a; 
struct 
{ 
int b; 
}; 
}; 

6.58無名struct/unionstructs/unions

領域所允許的通過ISO C11

但是它有什麼好處?

因爲無論如何我可以訪問數據成員相同的方式像

int main() 
{ 
struct st s; 
s.a=11; 
s.b=22; 
return 0; 
} 

編譯上的gcc 4.5.2,

gcc -Wall demo.c -o demo 

和沒有錯誤,

+0

可能的重複[什麼是在C11中有用的匿名結構和聯合?](http://stackoverflow.com/questions/8932707/what-are-anonymous-structs-and-unions-useful-for-in- c11) –

回答

14

它不一定是一個結構體內的匿名結構體,我不覺得它非常有用:它通常只會通過引入更多的填充來改變佈局,沒有其他可見的效果(與內聯子結構體放入父結構體中)。

我認爲匿名結構/聯合的優勢在其他地方: 它們可用於將匿名結構放入結構中的聯合或匿名聯合中。

例子:

​​
+1

你能解釋一下如何使用這個聯合?例如,如果我有u的實例x並使用'x.b1 ='a'',那麼其餘的b2,b3,b4會被初始化並佔用內存空間嗎? – Herbert

+0

@Herbert與聯合中的傳統(命名)結構相同。你的問題實際上是關於包含結構的工會。你應該問它作爲一個SO問題,而不是作爲對更具體問題的答案的評論,但是由於你做了後者,'x.b1 ='a''不會初始化成員'b2','b3' ,'b4',但是這些會「佔用內存空間」,這可以通過打印sizeof(union u)的值來看出。理論上,如果你聲明一個'union u'變量,你只使用'b1'成員,一個足夠聰明的編譯器可能只爲'b1'保留內存,... –

+0

@Herbert,但是原則上聲明一個'union u'對象意味着你可能想寫入它後面包含的結構的任何成員,所以應該爲它們保留內存。 –

11

的好處是很明顯,不是嗎?它節省了程序員的名字!由於naming things is hard,如果沒有真正需要,可以避免這樣做是很好的。

這也是一個非常明確的信號,這struct是局部的,從來沒有其他任何地方使用,但在被父結構,這是一個真正的現場,非常好的信息的情況下,因爲它減少了不必要的耦合可能性

把它想象成static;它將內部struct的可見性限制爲外部可見性,其方式類似於(但不等同於)static如何限制全局符號對其出現的編譯單元的可見性。

+0

小小精心..靜態??還有一個,如果那個是本地內部然後使用相同的名稱的標識符給出錯誤..但在函數中,我們可以在{}中給予相同的名稱標識符,因爲塊範圍爲什麼不允許在這裏結構{} – Omkant

+4

'struct'變得如此局部,以至於很難理解程序員爲什麼不直接在父結構中內聯其成員。目前版本中的這個答案沒有列出關於該替代方案的任何好處。嵌套結構與內聯成員(與更多的填充,這可能是預期的效果,但通常被認爲是缺點)相比,佈局是不同的。 –

+0

由於上述原因,似乎匿名'聯合'比匿名結構更有優勢。 – sherrellbc

1

我只是跑進匿名union一個巨大的好處。不過要注意的是,這不是一個暗戀的故事,也不是一個推薦的做法。

在一個包含數百個源代碼文件的早期C程序中,有一個全局變量struct,其中包含一個struct作爲成員。因此,對於全局變量的類型定義神情有些東西一樣:

typedef struct { 
    LONG  lAmount; 
    STRUCTONE largeStruct; // memory area actually used for several different struct objects 
    ULONG  ulFlags; 
} STRUCTCOMMON; 

struct,STRUCTONE,是幾個大的結構一個不過其他人在這個代碼寫的時間比STRUCTONE所有小。所以這個內存區域largeStruct被當作union使用,但沒有正確的源語句表明如此。而是使用memcpy()將各種變量struct複製到此區域。更糟的是,有時這是通過全局變量的實際名稱,有時是通過指向全局變量的指針。

通常隨着時間的推移最近的變化導致其中一個結構成爲最大的結構。我面臨着不得不通過一百個文件尋找這個被使用的地方以及所有不同的別名和其他所有內容。

然後我想起匿名工會。所以我修改了typedef爲以下:

typedef struct { 
    LONG  lAmount; 
    union { 
     // anonymous union to allow for allocation of largest space needed 
     STRUCTONE largeStruct; // memory area actually used for several different struct objects 
     STRUCTTHREE largerStruct; // memory area for even larger struct 
    }; 
    ULONG  ulFlags; 
} STRUCTCOMMON; 

然後重新編譯每一件事情。

所以現在所有這些日子的源代碼審查和迴歸測試我都不高興地期待不再需要。

我現在可以開始慢慢修改源代碼的過程,使用這個全局代碼將這個源代碼更新到我自己的時間表上更現代的標準。