2013-04-12 50 views
0

在結構/類的常見情況下,成員之間可能會有對齊填充。但我想知道這是否是安全的假設,這種特殊情況:相同類型的數組成員之後的對齊

template<typename T, size_t N> 
struct MyStruct { 
    T data[N]; 
    T term; 
    constexpr MyStruct(); 
}; 

將是這個可靠的等價物:

template<typename T, size_t N> 
struct MyStruct { 
    T data[N+1]; 
    constexpr MyStruct(); 
}; 

之所以問的是什麼其實我想要的是能夠在constexpr構造函數中顯式初始化數組的最後一個成員(但我不關心其餘部分)。例如與頂級MYSTRUCT我可以這樣做:

template<typename T, size_t N> 
constexpr MyStruct<T,N>::MyStruct() : data{}, term{0} {} 

但我希望得到的結果是一樣的,如果長期是真的數組的最後一個元素。

這是安全嗎?如果沒有,是否有辦法使用MyStruct的第二種形式來實現相同的功能?

+1

根據§5.3.6,數組和類型具有相同的對齊方式,所以不應該有任何填充。但在§9.2中它說:「[...]執行對齊要求可能會導致兩個相鄰的成員不能立即分配;因此可能需要管理虛擬功能(10.3)和虛擬基類(10.1)的空間。」 _任何人都可以構造一個失敗的案例嗎? – 2013-04-12 14:53:51

+0

謝謝,這很有用。我已經嘗試過使用gcc進行各種實驗,但還沒有發現失敗。我只玩簡單的結構,我目前的用例不需要涉及虛擬類型。 – GeoffW

+1

我會試圖使用'union'並至少做一些'static_assert'大小的數學。有些'assert'數學來確保'&two.last ==&one.arr [N-1]'。 – Yakk

回答

0

這是絕對不安全的假設您的數據[N]和您的術語變量之間沒有差距。例如,您可以明確地控制Microsoft編譯器如何將變量對齊n字節邊界(其中n爲1,2,4,8或16),請參閱http://msdn.microsoft.com/en-us/library/xh3e3fd0(v=vs.80).aspx

+0

鏈接的文章說:「當您指定此選項時,第一個之後的每個結構成員都存儲在成員類型的大小或n字節邊界(其中n爲1,2,4,8或16)* *以較小者爲準**。「因此,在我看來,編譯器仍然可以選擇將相似類型放在一起 - 實際上,這種表述似乎表明我是安全的(鑑於數據[N]和術語與上述類型相同)。 – GeoffW

+0

當然,如果你可以自由選擇/ Zp1與微軟編譯器,那麼你會沒事的。但是如果你編寫的代碼可能在許多編譯器上使用,那麼你絕對不會這麼做,即使對於微軟來說,你可能會發現/ Zp1與你正在做的其他事情相沖突。我的建議是試着尋找另一種方式,然後你不必擔心這一點。根據我的經驗,這些低級別問題總是會回來並最終咬你! – Stochastically

+0

請注意,「以較小者爲準」是指在成員的大小和對齊方式之間的選擇 - 所以/ Zp開關應該無關緊要。字符仍然會以1對齊(沒有間距,因爲陣列在該邊界上完成),單詞爲2,依此類推。如果T的結構尺寸超過了對齊尺寸,結果會變得更復雜,但似乎測試結果還不錯。但是,我確實對低層次問題重新審視一下。 – GeoffW

相關問題