zoukankan      html  css  js  c++  java
  • 关于 Lo、Hi、LoWord、HiWord  转万一

    LoWord()得到一个32bit数的低16bit  
    HiWord()得到一个32bit数的高16bit
    Lo()得到一个16bit数最低(最右边)那个字节
    Hi()得到一个16bit数最高(最左边)那个字节

    取32位longint型数的 
    高16位数为 hiword(longint-var)  
    低16位数为 loword(longint-var)  

    取16位数的 
    高8位数为 hibyte(integer_var)  
    低8位数为 lobyte(integer_var)  
    Cardinal 是 4 字节无符号的整型, 先看一个例数:

    Cardinal 例数: 4277991664
    按字节划分: 第四字节 第三字节 第二字节 第一字节
    二进制: 11111110 11111100 11111000 11110000
    十六进制: FE FC F8 F0
    十进制: 254 252 248 240
    按双字节划分: 高两位 低两位
    二进制: 1111111011111100 1111100011110000
    十六进制: FEFC F8F0
    十进制: 65276 63728

    
    
    
    //可以用 Lo 函数提取它的低字节(也就是第一个字节)
    const
      c: Cardinal = 4277991664;
    begin
      ShowMessageFmt('%d', [Lo(c)]); {240}
    end;
    

    //其实不使用 Lo 函数, 通过 Byte 类型转换也可以获取第一个字节
    const
      c: Cardinal = 4277991664;
    begin
      ShowMessageFmt('%d', [Byte(c)]); {240}
    end;
    

    //Hi 函数说是获取高位字节, 其实是获取第二个字节
    const
      c: Cardinal = 4277991664;
    begin
      ShowMessageFmt('%d', [Hi(c)]); {248}
    end;
    

    //如果要获取低两位, 貌似应该有个 LoWord 函数; 确实有, 但它不是函数, 只是 Word 类型的一个别称.
    const
      c: Cardinal = 4277991664;
    begin
      ShowMessageFmt('%d', [LoWord(c)]); {63728}
      ShowMessageFmt('%d', [Word(c)]);   {63728}
    end;
    

    //HiWord 函数是提取高两位的
    const
      c: Cardinal = 4277991664;
    begin
      ShowMessageFmt('%d', [HiWord(c)]); {65276}
    end;
    

    说说 LoWord 和 HiWord 的用途:

    譬如在一个鼠标消息的消息参数 lParam 中存放着鼠标位置. lParam 是 4 字节的, 它的低两位存放 x、高两位存放 y ...

    我在这个例子中用到过: http://www.cnblogs.com/del/archive/2008/04/19/1160968.html

    本话题会涉及到: Lo、Hi、HiByte、LoWord、HiWord、MakeWord、MakeLong、Int64Rec
    --------------------------------------------------------------------------------

    譬如有一个 Cardinal 类型的整数: 1144201745
    其十六进制的表示是: $44332211
    其二进制表示是: 01000100 00110011 00100010 00010001
    我们说 Cardinal 是 32 位的整数, 这里的位是指 "二进制的位数", 不信你数数.

    我们需要重点面对的是十六进制, 不管是几进制的数在编译成汇编代码时都是用十六进制表示, 因为它最直观;
    我们用十六进制来分析, 也是因为它的直观.

    怎么直观的? Cardinal 有 32 位, 每 8 位一个字节, 共 4 个字节;
    上面的例数分成字节就是: $44、$33、$22、$11, 这明显比二进制简洁、比十进制直观.

    其中的 $11 是最低位的字节、$44 是最高位的字节(每字节对应十六进制的两位).
    有时我们需要获取其中某个字节或某两个字节, 这虽然用位运算也不难, 但还是有了诸多函数:
    --------------------------------------------------------------------------------
     
    Lo     //获取例数中的 $11
    Hi     //获取例数中的 $22
    LoWord //获取例数中的 $2211
    HiWord //获取例数中的 $4433
    --------------------------------------------------------------------------------
    其中的 Hi 好像有点费解, 为什么获取的不是 $44 而是 $22 呢? 
    这样理解吧: Hi 获取的是 Lo(获取)的上一个字节.

    HiByte 和 Hi 基本一样, 如果参数是 16 位的 Word 类型, 用 HiByte 会更好些(中间会省去一个转换过程).

    其中的 HiWord 是个函数, 但 LoWord 并不是个函数, 它是 Word 类型的重命名.
    也就是说 LoWord(num) 等价于 Word(num), 这不是类型转换吗?
    是的, 所以像 Lo(num) 也可以用 Byte(num) 来代替.
    --------------------------------------------------------------------------------

    用代码总结一下:
    --------------------------------------------------------------------------------
     
    var
      num: Cardinal;
      b1,b2,b3,b4: Byte;
      w1,w2: Word;
    begin
      num := $44332211;
      w1 := Word(num);
      w2 := HiWord(num);
      ShowMessageFmt('w1:%x; w2:%x', [w1,w2]);//w1:2211; w2:4433

      b1 := Lo(num);
      b2 := Hi(num);
      b3 := Byte(w2);
      b4 := HiByte(w2);
      ShowMessageFmt('b1:%x; b2:%x; b3:%x; b4:%x', [b1,b2,b3,b4]);//b1:11; b2:22; b3:33; b4:44
    end;
    --------------------------------------------------------------------------------
    下一个话题: 我们有时也需要进行上面的反操作, 譬如:
    把两个 Byte 合成为一个 Word;
    把两个 Word 合成一个 Cardinal;
    把两个 Cardinal 合成一个 Int64;
    把四个 Byte 合成一个 Cardinal;
    把四个 Word 合成一个 Int64 等等

    上面说的 Cardinal 也可以是 Integer 或 DWORD.

    完成这种工作也有不少函数:
    MakeWord、MakeLong、MakeWParam、MakeLParam、MakeLResult、MAKELCID 等等.

    仅就 MakeWord、MakeLong 举例:
    --------------------------------------------------------------------------------
     
    var
      num: Cardinal;
      b1,b2,b3,b4: Byte;
      w1,w2: Word;
    begin
      b1 := $11;
      b2 := $22;
      b3 := $33;
      b4 := $44;

      w1 := MakeWord(b1, b2);
      w2 := MakeWord(b3, b4);
      ShowMessageFmt('w1:%x; w2:%x', [w1,w2]);//w1:2211; w2:4433

      num := MakeLong(w1, w2);
      ShowMessageFmt('num:%x', [num]);//44332211
    end;
    --------------------------------------------------------------------------------
    有没有把两个 Integer 合成为 Int64 的函数呢?
    没有, 当然可以写一个; 不过有更方便的处理方式, 那就是 Int64Rec 结构.

    举例如下:
    --------------------------------------------------------------------------------
     
    var
      n1,n2: Cardinal;
      num64: Int64;
      rec: Int64Rec;
    begin
      n1 := $44332211;
      n2 := $AABBCCDD;

      rec.Lo := n1;
      rec.Hi := n2;

      num64 := Int64(rec);
      ShowMessage(IntToHex(num64, 0)); //AABBCCDD44332211
    end;
    --------------------------------------------------------------------------------
    Int64Rec 更多用于反向操作:
    --------------------------------------------------------------------------------
     
    var
      n1,n2: Cardinal;
      num64: Int64;
    begin
      num64 := $AABBCCDD44332211;

      n1 := Int64Rec(num64).Lo; //或 n1 := Cardinal(num64);
      n2 := Int64Rec(num64).Hi;

      ShowMessageFmt('n1:%x; n2:%x', [n1,n2]);//n1:44332211; n2:AABBCCDD
    end;

  • 相关阅读:
    浙江理工2015.12校赛-F Landlocked
    浙江理工2015.12校赛-G Jug Hard
    浙江理工2015.12校赛-B 七龙珠
    浙江理工2015.12校赛-A
    Smallest Bounding Rectangle
    Just a Hook(HDU1698 线段树的简单应用)
    覆盖的面积(HDU 1255 线段树)
    Prime Query (ZOJ 3911 线段树)
    JuQueen(线段树 lazy)
    2015弱校联盟(2)
  • 原文地址:https://www.cnblogs.com/luckForever/p/7254605.html
Copyright © 2011-2022 走看看