15

C / C ++では、常に

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

Pascal / Delphiでは、「packed array」を使用して上記のアサーションが真であることを確認できますが、「packed」指定子はDelphiの配列に実用的な値を持っていますか?'unpacked'配列の例を作成できません。配列は常に'packed'のようです。

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レコードは異なります。フィールドの配置により、構造体のサイズがフィールドのサイズの合計よりも大きくなるように、「アンパック」することができます。)

4

2 に答える 2

27

Delphiでは実際的な効果はありません。合理的に影響を与える可能性のある唯一のタイプは、アラインメントとサイズの組み合わせが最も奇妙なタイプでExtended、サイズは10、アラインメントは8です。ただし、の配列Extendedは基本的にすでにパックされています(ただし、アラインメントは8のままです。packedディレクティブはレコードの場合と同じように機能し、1)の配置になります。

Extended配列が影響を与える可能性がある唯一のタイプであると言うのはなぜですか?他のDelphiタイプ、組み込み、または作成できるものはありません。サイズは、その配置の整数倍ではありません(Delphiの古いバージョンといくつかのバグは別として)。アラインメントは、パディングによってレコードを大きくするものです。これにより、すべてのフィールドがそのタイプの配置の整数倍であるオフセットで開始するように、フィールドの間隔が空けられます。配列の類似のケースでは、関係するタイプは1つだけであり、サイズがすでにタイプの配置の倍数である場合は、パディングは必要ありません。

Extendedこれは、レコードにラップされているかどうかに応じて、サイズと配置にどのように影響するかを示すプログラムです。packed配列に追加して、違いがないことを確認できます。

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.

アラインメントとpacked:についてのより多くの言葉packedパディングが追加されていないことを保証するだけでなく、(レコードに対して)別の効果があります。レコード自体に1の位置合わせがあることもマークされます。これは、他の場所で使用すると、レコードが頻繁に位置ずれするという悪影響があります。言語/OSの相互運用性の目的で、他の言語がOSアラインメントルール(通常はCアラインメントルールを意味する)を使用していない場合にのみ、パックされたディレクティブを使用する必要があります。(一部のWindows APIヘッダーは、その中で定義された型に対して誤った配置になっています。それ以来、それを使用する必要があります。)一方、ファイル形式との互換性のために、packedは正当化される場合がありますが、タイプの選択に関しては、他にも多くの懸念事項があります(たとえば、整数は16ビットDelphiでは2バイトでしたが、その後は4バイトでした)。

Delphiは、アライメントにC互換のルールを使用しようとします。過去には、ここにいくつかのバグがありました(特に、TRec =レコードA、B:拡張終了、対TRec =レコードA:拡張、B:拡張終了などのレコード)が、これらのバグは今すぐ修正する必要があります

于 2011-01-03T12:11:24.857 に答える
2

Delphi XEヘルプは、動的配列についてこれを述べています

動的配列メモリレイアウト(Win32のみ):

オフセットコンテンツ

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

だから、そのドキュメントによってそれは詰め込まれています。

于 2013-06-17T18:13:10.577 に答える