考慮下面的工會:我們可以使用工會進行類型轉換嗎?
union{
uint32_t a;
uint64_t b;
};
兩個a
和b
駐留在同一存儲區域。如果我們將32位整數a
初始化爲某個值,那麼如何獲得b
(當b
未初始化時)?這是否意味着,編譯器在內部轉換a到b
感謝
考慮下面的工會:我們可以使用工會進行類型轉換嗎?
union{
uint32_t a;
uint64_t b;
};
兩個a
和b
駐留在同一存儲區域。如果我們將32位整數a
初始化爲某個值,那麼如何獲得b
(當b
未初始化時)?這是否意味着,編譯器在內部轉換a到b
感謝
在uint64_t
額外的字節將有一個未確定的值。
從C standard的節6.2.6.1:
當值被存儲在聯合類型的對象的一員,所述對象表示的不 字節對應於會員,但確實與其他會員取得 未指定的值。
而第6.5.2.3:
後綴表達式接着
.
操作者和標識符指定結構或聯合對象的成員。 值是指定成員的值,95)並且如果 是第一個表達式是左值,則該值爲左值。如果第一個表達式 具有限定類型,結果具有 所謂合格版本指定構件95)如果構件用於讀取聯合對象的內容的類型不一樣成員最後用於在對象中存儲值 值的對象表示的相應部分是 在6.2.6中描述的新類型中重新解釋爲對象表示形式爲 (有時稱爲「類型雙引號」 )。 這可能是一個陷阱表示。
唯一允許的是如果您有一個或多個結構體的聯合體,並且每個結構體都具有相同類型的初始成員。
從部分6.5.2.3:
一個特殊的保障是爲了簡化使用工會提出:如果一個聯合包含共享 公共初始序列幾種結構(見下文) ,並且如果聯合對象 當前包含這些結構中的一個,則允許 檢查聯合體的完成類型的聲明可見的任何位置的任何公共初始部分。如果對應的 成員對於一個或多個初始成員的序列具有兼容類型(以及對於位域相同的寬度) ,則兩個 結構共享共同的初始序列。
下面是一個例子,這可能是有用的:在不同類型的插槽
union sockadddr_u {
struct sockaddr sa;
struct sockaddr_un sun;
struct sockaddr_in sin;
}
這些結構存儲信息。大多數成員不同,但每個成員的第一個成員的類型爲sa_family_t
,它告訴您套接字類型。這允許您檢查這些成員中的第一個成員,以確定哪些成員包含其內部成員的有意義數據。
它真的是UB嗎?我的意思是:是不是一個平臺依賴和實現定義的行爲? – LPs
未指定的值不是不確定的值。該標準還明確允許通過聯合http://port70.net/~nsz/c/c11/n1570.html#note95進行類型雙擊。如果目標類型具有陷阱表示,則它定義了非常多的實現(而不是UB)。 – StoryTeller
@dbush謝謝你'它們中任何一個的共同初始部分'意味着兩個結構具有相同的字段(結構的所有字段相同的類型和相同的數字)。但是爲什麼我會有一個類似的結構的聯盟,那會是什麼樣的使用呢? – Bionix1441
我很確定編譯器不會轉換任何東西,而這樣做是未定義的行爲。 – melpomene
將'a'設置爲'int',在內存中寫入4個字節。訪問'b'你正在讀取4個字節的內存作爲'float':有什麼問題? – LPs
@LPs我在32位平臺上。 – Bionix1441