Are there any difference between array and packed array in Delphi?

≯℡__Kan透↙ 提交于 2019-11-28 08:25:12

It has no practical effect in Delphi. The only type it could reasonably affect is the type with the oddest alignment and size combination, Extended, which has a size of 10 and an alignment of 8. However, arrays of Extended are essentially packed already (though they still have an alignment of 8; if the packed directive worked like it did on records, they would have an alignment of 1).

Why do I say arrays of Extended is the only type it could affect? There is no other Delphi type, built-in or that you can compose, which has a size that is not an integer multiple of its alignment (leaving aside older versions of Delphi, and some bugs). Alignment is the thing that makes records larger with padding; it causes fields to be spaced out so that every field starts at an offset which is an integer multiple of its type's alignment. In the analogous case with arrays, there is only one type involved, and if the size is already a multiple of the type's alignment, then there's no need for padding.

Here's a program which shows how Extended affects size and alignment depending on whether it's wrapped in a record or not; you can add packed to the arrays, and see it makes no difference:

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 words about alignment and packed: packed has another effect (on records) rather than just guaranteeing that there is no padding added: it also marks the record as having itself an alignment of 1. This has the negative effect of causing it to be frequently misaligned when it is used elsewhere. For purposes of language / OS interoperability, only in the case where the other language is not using OS alignment rules (normally meaning C alignment rules) should the packed directive be used. (Some Windows API headers have incorrect alignment for types defined within them, mind you, and have had to live with it ever since.) For purposes of compatibility with a file format, on the other hand, packed may be justified, but there are lots of other concerns there too, with respect to type choice (e.g. Integer was 2 bytes in 16-bit Delphi, but 4 bytes subsequently).

Delphi tries to use C-compatible rules for alignment. In the past, it had some bugs here (particularly with records like TRec = record A, B: Extended end; versus TRec = record A: Extended; B: Extended end;), but these bugs should be fixed now

Delphi XE Help says this for dynamic arrays

Dynamic array memory layout (Win32 only):

Offset Contents

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

So, by that doc it is packed.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!