2011-01-03 18 views
15

hep Pascal/DelphiDelphi'de dizi ile paketlenmiş dizi arasında fark var mı? C/C++ olarak

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

sahip yapabilirsiniz yukarıdaki assert doğrudur, ama yok 'dolu' belirleyicisi diziler için herhangi pratik değer içinde olduğundan emin olmak için 'paketlenmiş dizi' kullanmak Delphi? Ben, diziler hep 'dolu' görünüyor 'paketlenmemiş' dizisinin bir örneğini oluşturamazsınız:

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++ yapıları ve Delphi kayıtları farklıdır - onlar 'paketlenmemiş' olabilir boyutu böylece yapının alanları alanların boyutlarının toplamından daha büyüktür.)

+0

Delphi derleyicisinin gelecekteki sürümleri "paketlenmiş" değiştirici olmadan, kompakt olmayan diziler kullanabilir. Şahsen ben 'tam olarak' ve sadece doğru bellek düzenini önemsersem kullanırım. – CodesInChaos

cevap

26

Delphi'de pratik bir etkisi yoktur. Makul bir şekilde etkileyebilecek tek tip, 10'luk bir boyuta ve 8'lik bir hizalamaya sahip olan, Extended sayılı en tuhaf hizalama ve boyut kombinasyonuna sahip olan tiptedir. Bununla birlikte, Extended dizileri halihazırda paketlenmiştir (yine de 8 packed yönergesi, kayıtlarda olduğu gibi çalıştıysa, 1) ile aynı hizaya gelecektir.

Neden Extended dizinin etkileyebileceği tek tür olduğunu söyleyebilirim? Yerleştirilebilen veya düzenleyebileceğiniz başka bir Delphi türü yoktur; bu, hizalamasının tam bir katı olmayan bir boyuta sahiptir (Delphi'nin eski sürümlerini ve bazı hataları bir kenara bırakır). Hizalama, kayıtları dolgu ile daha büyük yapan şeydir; Her alanın, türünün hizalanmasının tamsayı katları olan bir ofsetle başlaması için alanların aralıklı olmasına neden olur. Diziler ile benzer durumda, sadece tek bir tür vardır ve boyut zaten türün hizalama birden fazla ise, o zaman dolgu için gerek yoktur.

Extended'un bir kayıtta olup olmadığına bağlı olarak boyutu ve hizalamayı nasıl etkilediğini gösteren bir program; sadece hayır dolgu eklendiğinden olduğunu garanti yerine packed (kayıtlarına) Başka bir etkiye sahiptir: diziler için packed ekleyin ve hiç fark etmez görebilirsiniz: hizalama ve packed hakkında

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. 

Daha kelimeler onu da kaydı, 1'in bir hizalamasına sahip olarak işaretler. Bu, başka bir yerde kullanıldığında sık sık yanlış hizalanmasına neden olmanın olumsuz etkisine sahiptir. Dil/OS birlikte çalışabilirliği amaçları için, yalnızca diğer dilin OS hizalama kurallarını (normalde C hizalama kuralları) kullanmadığı durumlarda paketlenmiş yönerge kullanılmalıdır. (Bazı Windows API üstbilgileri, kendi aralarında tanımlanmış türler için yanlış hizalamaya sahiptir, sizden bu yana ve bununla birlikte yaşamak zorunda kalmıştır.) Bir dosya biçimiyle uyumluluk amacıyla, paketlenmiş, ancak haklı olabilir. tip seçimi ile ilgili olarak diğer birçok endişe de var (örneğin, Tamsayı 16 bit Delphi'de 2 bayt, ancak daha sonra 4 bayt).

Delphi, hizalama için C-uyumlu kurallar kullanmayı dener. Geçmişte, burada bazı hatalar vardı (özellikle TRec = Kayıt A, B: Genişletilmiş uç; TRec = A: Geniş: B: Uzatılmış sonu;), ancak bu hatalar şimdi düzeltilmelidir

+0

Çok ilginç, teşekkürler. Umarım Uzatılmış 64-bit derleyicide hayatta kalacaktır ve iki katına çıkmayacaktır. – kludg

+0

Kayıtlar için örtük hizalama = 1 paketlenmiş utanç verici değildir. En azından konuya ilk geldiğimde bakmadım! –

0

İçeriği Yani, doc tarafından o doludur

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

Offset: XE Delphi Yardım

dinamik dizi bellek düzeni (Win32 için) dinamik diziler için bu diyor.