我想在Delphi中声明一个包含与C中相同的布局的记录。
对于感兴趣的人:此记录是Windows操作系统的LDT_ENTRY记录中的联合的一部分。 (我需要在Delphi中使用这个记录,因为我正在Delphi中使用XBox模拟器 – 请参阅sourceforge上的项目Dxbx)。
无论如何,有关记录定义为:
struct { DWORD BaseMid : 8; DWORD Type : 5; DWORD Dpl : 2; DWORD Pres : 1; DWORD LimitHi : 4; DWORD Sys : 1; DWORD Reserved_0 : 1; DWORD Default_Big : 1; DWORD Granularity : 1; DWORD BaseHi : 8; } Bits;
据我所知,Delphi没有可能的位域。我试过这个:
Bits = record BaseMid: Byte; // 8 bits _Type: 0..31; // 5 bits Dpl: 0..3; // 2 bits Pres: Boolean; // 1 bit LimitHi: 0..15; // 4 bits Sys: Boolean; // 1 bit Reserved_0: Boolean; // 1 bit Default_Big: Boolean; // 1 bit Granularity: Boolean; // 1 bit BaseHi: Byte; // 8 bits end;
但是唉:它的大小变成10字节,而不是预期的4。
我想知道我应该如何申报记录,以便我获得相同布局,大小和相同成员的记录。优选没有吸气剂/固定剂的负载。
TIA。
解决方法
感谢大家!
根据这些信息,我将其简化为:
RBits = record public BaseMid: BYTE; private Flags: WORD; function GetBits(const aIndex: Integer): Integer; procedure SetBits(const aIndex: Integer; const aValue: Integer); public BaseHi: BYTE; property _Type: Integer index $0005 read GetBits write SetBits; // 5 bits at offset 0 property Dpl: Integer index $0502 read GetBits write SetBits; // 2 bits at offset 5 property Pres: Integer index $0701 read GetBits write SetBits; // 1 bit at offset 7 property LimitHi: Integer index $0804 read GetBits write SetBits; // 4 bits at offset 8 property Sys: Integer index $0C01 read GetBits write SetBits; // 1 bit at offset 12 property Reserved_0: Integer index $0D01 read GetBits write SetBits; // 1 bit at offset 13 property Default_Big: Integer index $0E01 read GetBits write SetBits; // 1 bit at offset 14 property Granularity: Integer index $0F01 read GetBits write SetBits; // 1 bit at offset 15 end;
索引编码如下:(BitOffset shl 8)NrBits。其中1≤NrBits<= 32且0 <= BitOffset = 31 现在,我可以得到并设置这些位如下:
{$OPTIMIZATION ON} {$OVERFLOWCHECKS OFF} function RBits.GetBits(const aIndex: Integer): Integer; var Offset: Integer; NrBits: Integer; Mask: Integer; begin NrBits := aIndex and $FF; Offset := aIndex shr 8; Mask := ((1 shl NrBits) - 1); Result := (Flags shr Offset) and Mask; end; procedure RBits.SetBits(const aIndex: Integer; const aValue: Integer); var Offset: Integer; NrBits: Integer; Mask: Integer; begin NrBits := aIndex and $FF; Offset := aIndex shr 8; Mask := ((1 shl NrBits) - 1); Assert(aValue <= Mask); Flags := (Flags and (not (Mask shl Offset))) or (aValue shl Offset); end;
很漂亮,你不觉得吗?
PS:Rudy Velthuis现在在他的优秀“Pitfalls of converting”-article中包含了这个修订版本。