关于 Lo、Hi、LoWord、HiWord 转万一
LoWord()得到一个32bit数的低16bit
HiWord()得到一个32bit数的高16bit
Lo()得到一个16bit数最低(最右边)那个字节
Hi()得到一个16bit数最高(最左边)那个字节
HiWord()得到一个32bit数的高16bit
Lo()得到一个16bit数最低(最右边)那个字节
Hi()得到一个16bit数最高(最左边)那个字节
取32位longint型数的
高16位数为
hiword(longint-var)
低16位数为 loword(longint-var)
低16位数为 loword(longint-var)
取16位数的
高8位数为
hibyte(integer_var)
低8位数为 lobyte(integer_var)
Cardinal
是 4 字节无符号的整型, 先看一个例数:低8位数为 lobyte(integer_var)
Cardinal 例数: | 4277991664 | |||
---|---|---|---|---|
按字节划分: | 第四字节 | 第三字节 | 第二字节 | 第一字节 |
二进制: | 11111110 | 11111100 | 11111000 | 11110000 |
十六进制: | FE | FC | F8 | F0 |
十进制: | 254 | 252 | 248 | 240 |
按双字节划分: | 高两位 | 低两位 | ||
二进制: | 1111111011111100 | 1111100011110000 | ||
十六进制: | FEFC | F8F0 | ||
十进制: | 65276 | 63728 |
//可以用 Lo 函数提取它的低字节(也就是第一个字节) constc: Cardinal = 4277991664; begin ShowMessageFmt('%d', [Lo(c)]); {240} end;
//其实不使用 Lo 函数, 通过 Byte 类型转换也可以获取第一个字节 constc: Cardinal = 4277991664; begin ShowMessageFmt('%d', [Byte(c)]); {240} end;
//Hi 函数说是获取高位字节, 其实是获取第二个字节 constc: Cardinal = 4277991664; begin ShowMessageFmt('%d', [Hi(c)]); {248} end;
//如果要获取低两位, 貌似应该有个 LoWord 函数; 确实有, 但它不是函数, 只是 Word 类型的一个别称. constc: Cardinal = 4277991664; begin ShowMessageFmt('%d', [LoWord(c)]); {63728} ShowMessageFmt('%d', [Word(c)]); {63728} end;
//HiWord 函数是提取高两位的 constc: Cardinal = 4277991664; begin ShowMessageFmt('%d', [HiWord(c)]); {65276} end;
说说 LoWord 和 HiWord 的用途:
譬如在一个鼠标消息的消息参数 lParam 中存放着鼠标位置. lParam 是 4 字节的, 它的低两位存放 x、高两位存放 y ...
我在这个例子中用到过:
本话题会涉及到:
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
begin
end;
--------------------------------------------------------------------------------
下一个话题: 我们有时也需要进行上面的反操作, 譬如:
把两个 Byte 合成为一个 Word;
把两个 Word 合成一个 Cardinal;
把两个 Cardinal 合成一个 Int64;
把四个 Byte 合成一个 Cardinal;
把四个 Word 合成一个 Int64 等等
上面说的 Cardinal 也可以是 Integer 或 DWORD.
完成这种工作也有不少函数:
MakeWord、MakeLong、MakeWParam、MakeLParam、MakeLResult、MAKELCID
等等.
仅就 MakeWord、MakeLong 举例:
--------------------------------------------------------------------------------
var
begin
end;
--------------------------------------------------------------------------------
有没有把两个 Integer 合成为 Int64 的函数呢?
没有, 当然可以写一个; 不过有更方便的处理方式, 那就是 Int64Rec 结构.
举例如下:
--------------------------------------------------------------------------------
var
begin
end;
--------------------------------------------------------------------------------
Int64Rec 更多用于反向操作:
--------------------------------------------------------------------------------
var
begin
end;