2012-03-21 34 views
8

我有下一個代碼:爲什麼記錄的大小不等於其字段大小的總和?

type TRecord1 = record 
    myarr: array [0..31] of single: 
end; 
type TRecord2 = record 
    b1, b2, b3, b4, b5, b6: byte; 
end; 
type TRecord3 = record 
    myarr: array [0..31] of single:  
    b1, b2, b3, b4, b5, b6: byte; 
end; 

procedure TForm1.FormCreate(Sender: Tobject); 
begin 
    ShowMessage(IntToStr(SizeOf(TRecord1))+'+'+IntToStr(SizeOf(TRecord2))+ 
     '='+IntToStr(SizeOf(TRecord3))); 
end; 

該程序將顯示以下信息:

128+6=136 

爲什麼SizeOf(TRecord3)等於136,而不是134?

+0

經驗法則:如果您打算在文件中使用某些結構 - 將它們聲明爲「packed」。 – OnTheFly 2012-03-21 15:03:22

+2

我的經驗法則是永遠不會將記錄的二進制表示寫入文件 – 2012-03-21 17:21:13

+0

是避免存儲二進制數據,但打包的指令在I/O(dll's,串行通信等)期間傳遞記錄時使用它。儘管使用標準化的二進制/字符串轉換技術應該適用於新的開發。 – 2012-03-21 18:11:08

回答

15

這是由於記錄對齊而添加的填充。由於它包含single值,因此TRecord3的對齊方式爲4。因此,填充將添加到記錄的末尾,以使大小成爲4的整數倍。這就是爲什麼大小是136而不是您期望的值134。

您可以聲明您的記錄爲packed,或者等價地將對齊編譯器選項設置爲$ALIGN 1。如果對齊爲1,則不會在記錄中添加填充和SizeOf(TRecord3)=134。不過,我強烈建議你不要這樣做。使用自然對齊會爲記錄提供最有效的內存訪問。例如,處理器加載未對齊的值比加載對齊的值要昂貴。對於singleinteger,自然對齊位於4字節的邊界上。對於double,自然對齊位於8字節的邊界上,依此類推。如果您需要與使用打包記錄的另一個庫進行二進制兼容,則應使用打包記錄。

+2

此外,您可以將聲明更改爲'輸入TRecord3 = packed record ...'以防止記錄對齊,儘管通常您不需要。對齊的記錄效果更好,但在某些情況下,您可能需要打包的記錄。 – GolezTrol 2012-03-21 11:04:58

4

這是由於對齊。記錄中的字段在4個字節或8個字節(或只有在記錄中使用字節時的字節)上對齊,以便在數組中所有字段的記錄將保持對齊。如果你想要公式起作用,你應該使用'打包記錄'。請注意,這些字段可能未對齊,可能會影響性能。

相關問題