gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 14:33:54 28 4
gpt4 key购买 nike

我想在 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 个字节。我想知道应该如何声明记录,以便获得具有相同布局、相同大小和相同成员的记录。最好没有大量的 getter/setter。

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 中包含了此版本的修订版本。 。

关于delphi - 如何模拟Delphi记录中的位域?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/282019/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com