如何模拟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://*.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 雪花ID


下一篇:Delphi中Indy10的IdTcpClient和IdTcpServer数据通信