陣列 – 在Delphi中array和packed陣列之間有什麼不同嗎?
在C/C++你總是有
SizeOf(array[N] of T) = N * SizeOf(T);
在Pascal / Delphi中,您可以使用“打包陣列”來確保上述assert是真實的,但是“包裝”說明符對於Delphi中的陣列有什麼實際價值?我無法建立“unpacked”陣列的示例,陣列似乎總是“打包”:
type A = array[0..2] of Byte; B = array[0..99] of A; C = packed record C1, C2, C3: Byte; end; D = array[0..99] of C; procedure TForm10.Button1Click(Sender: TObject); begin Assert(SizeOf(A) = 3); Assert(SizeOf(B) = 300); Assert(SizeOf(D) = 300); end;
(C/C++結構和Delphi記錄是不同的 – 它們可以“解包”,因此,由於欄位的對齊,結構的大小大於欄位大小的總和).
在Delphi中沒有實際的效果.可以合理影響的唯一型別是具有最奇怪的對齊和大小組合的型別,擴充套件,其大小為10,對齊為8.然而,擴充套件的陣列基本上已經被打包(儘管它們仍然具有8的對齊方式;如果打包指令像記錄一樣工作,它們將具有1).
為什麼我說擴充套件陣列是唯一可以影響的型別?沒有其他Delphi型別,內建的或者可以組合的,它的大小不是整數倍的整數(留下舊版本的Delphi,還有一些bug).對齊是使填充記錄更大的事情;它會使欄位間隔開,以便每個欄位以其型別對齊的整數倍的偏移開始.在類似於陣列的情況下,僅涉及一種型別,如果大小已經是型別對齊的倍數,則不需要填充.
這是一個程式,顯示擴充套件如何影響大小和對齊方式,取決於它是否包含在記錄中;你可以新增包裝到陣列,看到它沒有什麼區別:
type TWrap = record X: Extended; end; // field size=10, align=8, => actual size=16 TArr1 = array[1..3] of TWrap; // 3*16 => size=48, align=8 TArr2 = array[1..3] of Extended; // 3 * 10 => size=30, align=8 TRec1 = record A: Byte; B: TArr1; end; TRec2 = record A: Byte; B: TArr2; end; var x: TRec1; y: TRec2; begin Writeln('Size of TArr1: ', SizeOf(TArr1)); Writeln('Alignment of TArr1: ', Integer(@x.B) - Integer(@x.A)); Writeln('Size of TArr2: ', SizeOf(TArr2)); Writeln('Alignment of TArr2: ', Integer(@y.B) - Integer(@y.A)); end.
更多關於對齊和打包的單詞:打包有另一個效果(在記錄上),而不僅僅是保證沒有新增填充:它也將記錄標記為自己的對齊方式1.這具有導致其頻繁的負面影響在其他地方使用時對齊.為了語言/作業系統的互操作性,只有在其他語言不使用OS對齊規則的情況下(通常意味著C對齊規則),才能使用打包指令. (某些Windows API標頭對於在其中定義的型別有不正確的對齊方式,請記住,自此以後就必須使用它).另一方面,為了與檔案格式相容,打包可能是合理的,但是有關於型別選擇(例如,整數在16位Delphi中為2位元組,隨後為4個位元組),還有許多其他問題.
Delphi嘗試使用C相容規則進行對齊.在過去,它有一些錯誤(特別是記錄如TRec =記錄A,B:擴充套件結束;與TRec =記錄A:擴充套件; B:擴充套件結束),但這些錯誤應該現在修復
http://stackoverflow.com/questions/4583985/are-there-any-difference-between-array-and-packed-array-in-delphi