zoukankan      html  css  js  c++  java
  • 如何模拟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;
    
    
  • 相关阅读:
    用算法合并数组
    Redis各个数据类型的使用场景
    seesion工作原理
    自删除道指令程序
    uva 1335
    《生活在Linux中》之:使用Bash就是使用Emacs
    手动配置S2SH三大框架报错(三)
    数据和C
    IOS之【地图MapKit】
    我工作这几年(五)-- Android学习4.5月总结(一)
  • 原文地址:https://www.cnblogs.com/marklove/p/14768491.html
Copyright © 2011-2022 走看看