Delphi中的数组和压缩数组之间有什么区别吗? [英] Are there any difference between array and packed array in Delphi?

查看:43
本文介绍了Delphi中的数组和压缩数组之间有什么区别吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 C/C++ 中,你总是有

In C/C++ you always have

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

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

In Pascal/Delphi you can use 'packed array' to be sure that the above assert is true, but does 'packed' specifier have any practical value for arrays in Delphi? I can't create an example of 'unpacked' array, the arrays seems always '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 记录是不同的 - 它们可以被解包",以便由于字段的对齐,结构的大小大于字段大小的总和.)

(The C/C++ structures and Delphi records are different - they can be 'unpacked' so that the size of the structure is greater than the sum of fields' sizes due to the fields' alignment.)

推荐答案

在Delphi中没有实际效果.它可以合理影响的唯一类型是具有最奇怪的对齐和大小组合的类型,Extended,它的大小为 10,对齐为 8.但是,Extended 基本上已经打包了(尽管它们的对齐仍然是 8;如果 packed 指令像在记录上一样工作,它们的对齐将是 1).

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).

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

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 Delp 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.

这是一个程序,它显示了 Extended 如何根据是否包含在记录中来影响大小和对齐;你可以将 packed 添加到数组中,看看它没有区别:

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.

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

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 Delp but 4 bytes subsequently).

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

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中的数组和压缩数组之间有什么区别吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆