arrays - Delphi中数组和压缩数组有什么区别?

标签 arrays delphi alignment packed

在 C/C++ 中你总是有

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

在 Pascal/Delphi 中,您可以使用“打包数组”来确保上述断言为真,但是“打包”说明符对于 Delphi 中的数组有任何实际值(value)吗?我无法创建“未打包”数组的示例,数组似乎总是“已打包”:

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;如果 packed 指令像在记录上那样工作,那么它们的对齐方式将为 1)。

为什么我说扩展数组是它唯一可以影响的类型?没有其他 Delphi 类型(内置的或您可以编写的)的大小不是其对齐的整数倍(不考虑旧版本的 Delphi 和一些错误)。对齐是通过填充使记录变大;它会导致字段间隔开,以便每个字段都以偏移量开始,该偏移量是其类型对齐的整数倍。在数组的类似情况下,只涉及一种类型,如果大小已经是类型对齐的倍数,则不需要填充。

这是一个程序,它显示了 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.

关于对齐和打包的更多说明:打包还有另一种效果(对记录),而不仅仅是保证没有添加填充:它还将记录标记为具有本身的对齐方式为 1。这会产生负面影响,导致其在其他地方使用时经常出现错位。出于语言/操作系统互操作性的目的,仅在其他语言不使用操作系统对齐规则(通常指 C 对齐规则)的情况下才应使用打包指令。 (请注意,某些 Windows API header 与其中定义的类型对齐不正确,从那时起就不得不忍受它。)另一方面,出于与文件格式兼容的目的,打包可能是合理的,但也有关于类型选择,还有很多其他问题(例如,Integer 在 16 位 Delphi 中为 2 个字节,但随后为 4 个字节)。

Delphi 尝试使用 C 兼容规则进行对齐。过去,它有一些错误(特别是像 TRec = record A, B: Extended end; 与 TRec = record A: Extended; B: Extended end; 这样的记录),但现在这些错误应该被修复

关于arrays - Delphi中数组和压缩数组有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4583985/

相关文章:

javascript - 根据值中的文本将数组拆分为小数组

python - 在 Python 3 中,如何交换二维 numpy 数组中的两个子数组?

java - Android中如何将大量静态文本转换为数组

delphi - 如何在twebbrowser上的框架中填充任何字段?

html - CSS 下拉菜单对齐问题

html - 如何将元素列表底部对齐?

python - Numpy:如何快速替换矩阵中的相等值?

delphi - Delphi 7 创建动画启动画面

delphi - 正确处理模态窗口 "Minimize"行为

C 结构大小对齐