如何模拟Delphi records中的位域

Posted marklove

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何模拟Delphi records中的位域相关的知识,希望对你有一定的参考价值。

展开查看·Delphi <-> C++ 基本语法对照表
 
http://blog.qdac.cc/?p=925
一、标志符命名:两个基本一样,除了保留的关键字,C/C++区分大小写外,剩下的基本一样。一般来说你可以用Delphi的习惯,但注意大小写就好。
二、运算符:
数学运算符:+、-、*是一样的,除在C++里就是一个/,不分div和/,两个整数直接就是相当于div,任意一个是浮点数就是浮点数。
比较操作符:这个C/C++的不等于是!=,而Delphi是<>
位运算符(C++ => Delphi,下同):位与(& => and)、位或(| => or)、位非(~ => not)、异或(^ => xor),左移(变量<<位数 =>变量 shl 位数)、右移(变量>>位数 => 变量 shr 位数)
逻辑运算符:与(&& => and)、或(|| => or)、非(! => not)
地址运算符:& => @
成员运算符:Delphi均为“.”,C++中指针实例的成员用 -> ,非指针实例的成员用“.”。
指针内容操作符:*指针 => 指针^
自运算符:变量++ =>Inc(变量),++整型变量 => 无,变量– => Dec(变量),变量+=值 => 变量:=变量+值,变量*=值 =>变量:=变量*值,依次类推,Delphi剩下的都没有
【注】在C++中,&同时被当作引用符号,如:int &a=b ,此时访问a的内容和访问b的内容是等价的。
三、语句
语句都是以“;”结束,复合语句在C++中是用大括号包含在一起,Delphi是begin/end,对应关系:
{ => begin
} => end
四、变量声明
C++中变量声明的位置不必一定在开始,但C的话规矩就和Delphi一样了。格式:
类型 变量名; => var 变量名:类型
常量的C++和Delphi一样都是用const修饰,同样,C++的变量和常量定义你可以随便在什么地方。
五、流程控制
条件判断:if(条件)/else if(条件)/else =>if  条件 then/else if 条件 then/else
分支选择:switch(变量){ case 值:语句;default:默认处理语句;}=>case 变量 of 值:语句 else 默认语句 end
while循环:while(条件)语句; => while 条件 do 语句;
repeat循环:do 语句 while(条件); => repeat 语句 until 条件;注意两个条件是相反的,一个是成立时继续,一个是直到不成立
for循环:for(初始化语句;结束条件;额外控制) 语句 => for 循环变量:=初始值 to/downto 目标值 do 语句
六、函数
C++不区分过程和函数,过程对于C++而言只是返回值为void的函数,Delphi中函数是要求有返回值,过程没有返回值,对应格式如下:
函数:
返回值类型 [修饰符] 函数名(函数参数){函数代码} => function 函数名(函数参数):返回值类型;[修饰符];begin 函数代码 end;
过程:
void  [修饰符] 函数名(函数参数){函数代码} => procedure函数名(函数参数):返回值类型;[修饰符];begin 函数代码 end;
【注】
如果函数参数传地址,Delphi的var类型定义,一般翻译成引用,当然也可以翻译成指针。如:
procedure Inc1(var x:Integer);
begin
Inc(x);
end;

procedure Inc1(var x:Integer);
begin
Inc(x);
end;
翻译成C++可以是:

void __fastcall Inc1(int &x)
{
x++;
}

void __fastcall Inc11(int x)
{
(
x)++;
}

void __fastcall Inc1(int &x)
{
x++;
}

void __fastcall Inc11(int x)
{
(
x)++;
}
加上__fastcall修饰符是因为Delphi的调用规则默认是fastcall,保持一致。
七、基本类型
C++没有集合类型,所以delphi中的set没有直接对应类型,但C++ Builder对应了一个Set模板类,咱们不说。只说基本类型之间的映射关系:
char => AnsiChar
wchar_t => WideChar
unsigned char => Byte
short => Smallint
unsigned short => Word
int => integer
unsigned int =>Cardinal
long => Longint
unsigned long =>Cardinal
__int64 => Int64
unsigned __int64 =>UInt64
enum 枚举类型名 {枚举值列表 } => type 枚举类型名=(枚举值列表)
struct 结构体类型名{成员定义}=> 结构体类型名=[packed] record 成员定义 end;
class 类型名[: public/protected/private 父类名]=> 类型名=class[(父类名)]
union 联合(共用体)类型名{成员定义} => 类型名=record case 类型 of 值:(成员定义); end;
位域在Delphi中没有对应的定义,只能定义为相应的类型,然后自己去检测标志位。
【注】C++中,结构、类和接口实际上没有什么本质的区别,C++的结构体一样可以有构造和析构函数,一样可以继承和重载函数,如果非要说有区别,那么最大的区别就是C++里结构体默认成员是公开的(public),而类默认是私有的(private),但你可以用完全同样的语法去规定各个成员的可见性。至于接口,C++中本身就是record的别名。
八、引用外部文件

include <文件名> =>uses 单元名 或 {$I 文件名}

include “文件名” => uses 单元名 或 {$I 文件名}

九、强制类型转换
(类型)值 => 类型(值)
dynamic_cast<类型>(变量) => 值 as 类型
Delphi的is可以用检查dynamic_cast的值是否为空来代替,另外,C++还有一堆static_cast/reinterpret_cast/const_cast等转换方式,但常用的是上面的方法。

```` begin var i:byte; i:=$F0; //11110000 showmessage(i.ToString);//240 i:=i shr 4; //00001111 showmessage(i.ToString);//15 end; ```` https://stackoverflow.com/questions/282019/how-to-simulate-bit-fields-in-delphi-records http://rvelthuis.de/articles/articles-convert.html#bitfields ```` 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; ```` ~ ```` 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; ```` ~1 ```` type TBits = record private FBaseMid : Byte;//ff 8 FTypeDplPres : Byte;//ff 5+2+1 =8 FLimitHiSysEa: Byte;//ff 4+1+1+1+1 =8 FBaseHi : Byte;//ff 8 //byte int or int64 .。。。。之类的避开地址位置不好对等情况 //总的来说RBits 是一块内存 自己位移 可以解决 8+5+6+8+5... 第一个8 FF够用第二个 5 需要位移 取反 第三个6 需要位移取反 。。 function GetType: Byte; procedure SetType(const AType: Byte); function GetDpl: Byte; procedure SetDbl(const ADpl: Byte); function GetBit1(const AIndex: Integer): Boolean; procedure SetBit1(const AIndex: Integer; const AValue: Boolean); function GetLimitHi: Byte; procedure SetLimitHi(const AValue: Byte); function GetBit2(const AIndex: Integer): Boolean; procedure SetBit2(const AIndex: Integer; const AValue: Boolean);

public
property BaseMid: Byte read FBaseMid write FBaseMid;
property &Type: Byte read GetType write SetType; // 0..31
property Dpl: Byte read GetDpl write SetDbl; // 0..3
property Pres: Boolean index 128 read GetBit1 write SetBit1;
property LimitHi: Byte read GetLimitHi write SetLimitHi; // 0..15

property Sys: Boolean index 16 read GetBit2 write SetBit2; 
property Reserved0: Boolean index 32 read GetBit2 write SetBit2; 
property DefaultBig: Boolean index 64 read GetBit2 write SetBit2; 
property Granularity: Boolean index 128 read GetBit2 write SetBit2; 
property BaseHi: Byte read FBaseHi write FBaseHi;

end;

function TBits.GetType: Byte;
begin
Result := (FTypeDplPres shr 3) and $1F;
end;

procedure TBits.SetType(const AType: Byte);
begin
FTypeDplPres := (FTypeDplPres and $07) + ((AType and $1F) shr 3);
end;

function TBits.GetDpl: Byte;
begin
Result := (FTypeDplPres and $06) shr 1;
end;

procedure TBits.SetDbl(const ADpl: Byte);
begin
FTypeDblPres := (FTypeDblPres and $F9) + ((ADpl and $3) shl 1);
end;

function TBits.GetBit1(const AIndex: Integer): Boolean;
begin
Result := FTypeDplPres and AIndex = AIndex;
end;

procedure TBits.SetBit1(const AIndex: Integer; const AValue: Boolean);
begin
if AValue then
FTypeDblPres := FTypeDblPres or AIndex
else
FTypeDblPres := FTypeDblPres and not AIndex;
end;

function TBits.GetLimitHi: Byte;
begin
Result := (FLimitHiSysEa shr 4) and $0F;
end;

procedure TBits.SetLimitHi(const AValue: Byte);
begin
FLimitHiSysEa := (FLimitHiSysEa and $0F) + ((AValue and $0F) shr 4);
end;

function TBits.GetBit2(const AIndex: Integer): Boolean;
begin
Result := FLimitHiSysEa and AIndex = AIndex;
end;

procedure TBits.SetBit2(const AIndex: Integer; const AValue: Boolean);
begin
if AValue then
FLimitHiSysEa := FLimitHiSysEa or AIndex
else
FLimitHiSysEa := FLimitHiSysEa and not AIndex;
end;

以上是关于如何模拟Delphi records中的位域的主要内容,如果未能解决你的问题,请参考以下文章

求大神指教C语言中的位域

记录C中的位域

澄清 C 中的位域排序语义

C 和 C++ 中的位域:它们在哪里使用?

共享库中的位域可移植性

C/C++ 位域知识小结