如果我定義一個char變量尺寸的結構和相應的可變
char a;
和具有單焦構件
struct OneChar {
char a;
};
這些都定義將具有「焦炭」的中的所有尺寸的結構編譯器? 我的疑問是,如果我們在結構中定義一個char變量,由於內存打包,它會佔用比char大小更多的大小嗎?
如果我定義一個char變量尺寸的結構和相應的可變
char a;
和具有單焦構件
struct OneChar {
char a;
};
這些都定義將具有「焦炭」的中的所有尺寸的結構編譯器? 我的疑問是,如果我們在結構中定義一個char變量,由於內存打包,它會佔用比char大小更多的大小嗎?
它取決於體系結構和編譯器。對於這種特殊情況,您應該安全,但請檢查Data Structure Padding。
下面是一個excerpt:
在x86 C結構的典型對準
數據結構成員都存儲 順序在存儲器中,使得在 的構件數據1下方的結構 將總是在Data2和Data2之前將始終存在Data3:
struct MyData { short Data1; short Data2; short Data3; };
如果類型「短」被存儲在存儲器的兩個 字節然後 以上 所示的數據結構中的每個成員將是2字節對齊。 Data1將 置於偏移量0處,將數據2置於偏移量2處,並將數據3置於偏移量4處。該 結構的大小將爲6字節。
的類型 結構的每個成員的通常具有默認 對準,這意味着它會, 除非 程序員另有要求,被一個 預先確定的邊界上對齊。
- 一個char(一個字節)爲1字節對齊的:在編譯爲32位x86時,以下 典型比對是有效的來自Microsoft,Borland公司,和 GNU 編譯器。
- 短(兩個字節)將是2字節對齊。
- int(四個字節)將以4字節對齊。
- 浮點數(四個字節)將以4字節對齊。
- 雙字節(八字節)將在Windows上以8字節對齊,在Linux上以4字節對齊。
這裏是 各類成員的結構,前 彙編共計8個字節:
struct MixedData { char Data1; short Data2; int Data3; char Data4; };
編譯後的數據結構 將被補充有填充 字節,以確保正確的對準 其每個成員:
struct MixedData /* after compilation */ { char Data1; char Padding0[1]; /* For the following 'short' to be aligned on a 2 byte boundary */ short Data2; int Data3; char Data4; char Padding1[3]; };
編譯後的si結構的現在是 現在12個字節。需要注意的是 最後一個成員填充了 需要的字節數符合最大類型的 結構。在這種情況下,3個字節是 添加到最後一個成員,以填充 結構爲長字的大小。
它可以改變結構的對準 以減少他們所需要的存儲器 通過改變 編譯器的取向(或「包裝」)的結構 成員(或符合的 現有格式)。
請求所述MixedData 結構上方對準以一個 字節邊界將具有編譯器 丟棄預先確定的對準成員 和沒有填充字節 將被插入。
雖然是 限定結構 構件的取向沒有標準的方式,一些編譯器使用#pragma 指令,以指定內 源文件打包。下面是一個例子:
#pragma pack(push) /* push current alignment to stack */ #pragma pack(1) /* set alignment to 1 byte boundary */ struct MyPackedData { char Data1; long Data2; char Data3; }; #pragma pack(pop) /* restore original alignment from stack */
這種結構將具有編譯 大小爲6個字節。上述指令 可從 Microsoft,Borland,GNU和其他許多 編譯器中獲得。
只要有一個成員,我認爲你是安全的假設。
所有a
s將具有相同的大小,無論他們是獨立的還是內部的結構。
結構內可能發生的情況是成員之間存在填充......但這也可能發生在「獨立」變量中。
也可以在最後一個成員之後進行填充(不只是成員之間)。 – caf 2009-10-08 21:35:29
當你得到一個結構體的大小時,它包含了填充字節。但是,如果您有類似以下內容:
void fun()
{
char c;
int n;
}
編譯器可以自由插入它認爲不管是什麼原因填充。所以,在獨立變量的情況下,填充可以在那裏,在結構的情況下,你就不會知道這種情況。
您列出的案例將打包爲所有我知道的ABI下的1字節結構。
但如果需要可移植處理更復雜的情況下,最好的做法是,當你需要通過像一招計算地址總是使用sizeof(struct OneChar)
計算內存大小時,並採取現場地址的偏移:
(char*)&(((struct OneChar*)0)->a) - (char*)0
我認爲結構中的第一個字段必須位於偏移量0處。另外,'
各種編譯器將優化以在結構之間或結尾添加填充。所以,在所有的編譯器或平臺上假設分配的大小看起來並不安全。檢查您的編譯器選項以設置struct padding。
例如,Visual Studio使用#pragma pack
指令來覆蓋默認優化。
我的實際疑問是,在單個成員結構中,內存填充是否會起作用? – Byju 2009-10-08 17:33:20