加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

如何模拟Delphi记录中的位域?

发布时间:2020-12-15 10:18:28 所属栏目:大数据 来源:网络整理
导读:我想在Delphi中声明一个包含与C中相同的布局的记录。 对于感兴趣的人:此记录是Windows操作系统的LDT_ENTRY记录中的联合的一部分。 (我需要在Delphi中使用这个记录,因为我正在Delphi中使用Xbox模拟器 – 请参阅sourceforge上的项目Dxbx)。 无论如何,有关记
我想在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中包含了这个修订版本。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读