2011-11-20 53 views
4

如果我有這樣的標準佈局類型:聯盟是標準佈局類型嗎?

struct sl_t 
{ 
    int a; 
}; 

和工會這樣的:

union un_t 
{ 
    int b; 
    double q; 
}; 

我可以投的,並使用工會與結構類型?也就是說,我可以假設聯盟本身是一種標準佈局類型,並且數據在內存開始時是一致的嗎?

un_t obj; 
sl_t * s = reinterpret_cast<sl_t*>(&obj); 
s->a = 15; 
assert(obj.b == 15); 

或者我必須把聯合變量&obj.b的地址?

請注意,我已經意識到,如果我存儲結構中的工會內部的C++ 11標準保證我可以訪問兩個sl_t ::和un_t :: B,指的是9.5-1。

+2

但是......是不是'&obj.b'都短,更安全嗎?我很好奇你的動機。 –

+0

我仍然需要圍繞它的reinterpret_cast。我主要好奇,但我確實有一個情況,它可以方便地依靠這個。 –

回答

3

似乎對準您的問題,看看pragma pack。 struct/union名稱只是引用已分配的內存塊,如果st_t.a在結構中通過添加更多成員而被置換,則您的投射將失敗,但如果它仍然是第一個成員,它將起作用,因爲聯合的所有成員指向與工會本身的地址相同。

請參閱C++標準9.2.17-21節: 「指向標準佈局結構對象的指針,使用reinterpret_cast適當轉換,指向其初始成員(或者如果該成員是位域,然後到它所在的單位),反之亦然。「

另請參見章節9.5聯合: 「1.在一個聯合中,最多有一個非靜態數據成員可以在任何時候處於活動狀態,也就是說,最多可以有一個非靜態數據會員可以在任何時候被存儲在一個工會[注:有一個特殊的保證是爲了簡化使用工會提出:如果標準佈局工會包含共享一個公共初始序列(9.2)幾個標準佈局結構,如果此標準佈局聯合類型的對象包含其中一個標準佈局結構,則允許檢查任何標準佈局結構成員的公共初始序列;參見9.2。 - 結束註釋]聯合的大小足以包含其最大的非靜態數據成員,每個非靜態數據成員都被分配好像它是結構的唯一成員。「

+0

我有興趣知道,沒有任何編譯器擴展,它是否有效。 –

+0

@ edA-qa mort-ora-y:我擴展了我的答案,是的,它是有效的,但正如我解釋的那樣。 – slashmais

+1

你的第二個評論,在標準中它確實保證工會成員的地址與地址本身相同?這是我未能找到的,但是,這會使我的轉換有效。是的,顯然,如果st_t.a不再是第一個成員,它將無法工作。 –