2011-01-03 33 views
15

Trong C/C++ bạn luôn cóCó bất kỳ sự khác biệt giữa mảng mảng và đóng gói trong Delphi?

SizeOf(array[N] of T) = N * SizeOf(T); 

Trong Pascal/Delphi bạn có thể sử dụng 'mảng đóng gói' để chắc chắn rằng các khẳng định trên là đúng, nhưng không specifier 'đóng gói' có bất kỳ giá trị thiết thực cho mảng trong Delphi? Tôi không thể tạo ra một ví dụ về mảng 'giải nén, các mảng dường như lúc nào cũng 'đóng gói':

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ấu trúc C/và hồ sơ Delphi là khác nhau - họ có thể 'giải nén' để kích thước của cấu trúc lớn hơn tổng kích thước của các trường do sự canh lề của các trường.)

+0

Tôi đoán không có phiên bản bổ sung 'đóng gói' trong tương lai của trình biên dịch delphi có thể sử dụng các mảng không nhỏ gọn. Cá nhân tôi sử dụng 'đóng gói' nếu và chỉ khi tôi quan tâm đến bố cục bộ nhớ chính xác. – CodesInChaos

Trả lời

26

Nó không có hiệu quả thực tế trong Delphi. Loại duy nhất nó có thể ảnh hưởng một cách hợp lý là loại có sự liên kết và kích thước nhỏ nhất, Extended, có kích thước 10 và căn chỉnh 8. Tuy nhiên, các mảng Extended về cơ bản đã được đóng gói (mặc dù chúng vẫn có liên kết 8 ; nếu chỉ thị packed hoạt động như đã thực hiện trên hồ sơ, họ sẽ có căn chỉnh 1).

Tại sao tôi nói mảng Extended là loại duy nhất nó có thể ảnh hưởng? Không có loại Delphi khác, được xây dựng trong hoặc bạn có thể soạn, có kích thước không phải là một bội số nguyên của sự liên kết của nó (để lại một số phiên bản cũ hơn của Delphi và một số lỗi). Căn chỉnh là thứ làm cho các bản ghi lớn hơn với đệm; nó làm cho các trường được đặt cách nhau sao cho mỗi trường bắt đầu tại một offset, là bội số nguyên của sự liên kết kiểu của nó. Trong trường hợp tương tự với mảng, chỉ có một loại có liên quan, và nếu kích thước đã là bội số của sự liên kết của loại, thì không cần phải đệm.

Đây là chương trình hiển thị cách Extended ảnh hưởng đến kích thước và căn chỉnh tùy thuộc vào việc nó được bao bọc trong bản ghi hay không; bạn có thể thêm packed đến mảng, và xem nó làm cho không có sự khác biệt:

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. 

More lời về sự liên kết và packed: packed có một hiệu ứng (trên hồ sơ) thay vì chỉ đảm bảo rằng không có đệm thêm: nó cũng đánh dấu các bản ghi là có chính nó một sự liên kết của 1. Điều này có tác động tiêu cực gây ra nó thường xuyên bị lệch hướng khi nó được sử dụng ở nơi khác. Vì mục đích của khả năng tương tác ngôn ngữ/hệ điều hành, chỉ trong trường hợp ngôn ngữ khác không sử dụng quy tắc căn chỉnh OS (thường có nghĩa là quy tắc căn chỉnh C) nên chỉ thị đóng gói được sử dụng. (Một số tiêu đề Windows API có sự liên kết không đúng đối với các kiểu được định nghĩa bên trong chúng, hãy nhớ bạn và phải sống với nó từ đó.) Vì mục đích tương thích với định dạng tệp, mặt khác, được đóng gói có thể hợp lý, nhưng có rất nhiều mối quan tâm khác có quá, đối với loại lựa chọn (ví dụ như Integer là 2 byte trong 16-bit Delphi, nhưng 4 byte sau đó).

Delphi cố gắng sử dụng các quy tắc tương thích với C để căn chỉnh. Trong quá khứ, nó có một số lỗi ở đây (đặc biệt là với các bản ghi như TRec = bản ghi A, B: Mở rộng kết thúc; so với TRec = bản ghi A: Mở rộng; B: Mở rộng kết thúc;), nhưng các lỗi này phải được sửa ngay bây giờ

+0

Rất thú vị, cảm ơn bạn. Tôi hy vọng mở rộng sẽ tồn tại trong trình biên dịch 64-bit và sẽ không được bí danh để tăng gấp đôi. – kludg

+0

Đó là một sự xấu hổ mà đóng gói ngụ ý alignment = 1 cho hồ sơ không được ghi nhận. Ít nhất đó không phải là lần cuối cùng tôi nhìn, khi tôi gặp vấn đề này! –

0

Delphi XE Help nói điều này cho mảng động

động bố trí bộ nhớ mảng (chỉ Win32):

offset Nội dung

-8 32-bit = reference-count 
-4 32-bit = length indicator (number of elements) 
0..Length * (size of element) -1 = array elements 

vì vậy, bởi doc rằng nó được đóng gói.

Các vấn đề liên quan