枚举集大小以x64为单位

时间:2015-05-19 21:39:16

标签: delphi enums 64-bit 32bit-64bit 32-bit

我发现一个SizeOf(set)在32位和64位上有所不同,下面的例子显示了32位的5个字节和64位的8个字节。但我没有找到有关64位SizeOf(集)变化的信息。是否有关于它的Embarcadero文档或编译器指令在32位和64位上获得类似的结果。

program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses System.SysUtils;

type
{ Enumeration of properties}
TProperty1 = (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14,
  p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28,
  p29, p30, p31, p32, p33, p34, p35, p36, p37);

TProperties1 = set of TProperty1;

begin
WriteLn(SizeOf(TProperties1));
ReadLn;
end.

2 个答案:

答案 0 :(得分:5)

回答你的问题。我无法在Embarcadero网站上找到关于差异的任何内容或改变行为的编译器指令。我的研究表明如下:

集合在32位中具有以下字节大小:

  • 最多8个元素 - 1个字节
  • 9到16个元素 - 2个字节
  • 17到32个元素 - 4个字节

从这一点开始,它会根据需要添加字节,一次添加一个字节。因此33到40个元素使用5个字节,41到48个元素使用6个字节。

在64位模式下,情况略有不同:

  • 最多8个元素 - 1个字节
  • 9到16个元素 - 2个字节
  • 17到32个元素 - 4个字节
  • 33到64个元素 - 8个字节

从这一点开始,它会根据需要添加字节,一次添加一个字节。因此,65到72个元素使用9个字节,73到80个元素使用10个字节。

要解决此问题,您需要在WriteSetTWriter.WriteProperty中使用TReader.ReadSet之类的内容,或者您​​可以执行以下操作:

procedure SaveSetToStream(aStream: TStream; const aSet: TProperties1);
var
  streamData: array[0..7] of byte;
begin
  Assert(SizeOf(aSet) <= SizeOf(streamData), 'Set is too large to save. Increase the array length.');
  FillChar(streamData, SizeOf(streamData), 0);
  Move(aSet, streamData, SizeOf(aSet));
  aStream.Write(streamData, SizeOf(streamData));
end;

function ReadFromStream(aStream: TStream): TProperties1;
var
  streamData: array[0..7] of byte;
begin
  Assert(SizeOf(Result) <= SizeOf(streamData), 'Set is too large to load. Increase the array length.');
  aStream.Read(streamData, SizeOf(streamData));
  Move(streamData, Result, SizeOf(Result));
end;

答案 1 :(得分:0)

另一种解决方法是确保32位机器可以从64位机器读取流,反之亦然是创建函数

function SizeCheck( const p : integer ) : integer;
begin
  if p in [5..8 ] then Result := 8 else Result := p; // adjust for 64 bit set sizes
end;  

然后使用

Stream.Write(set, SizeCheck(SizeOf(set)));

显然只用于套装。