首页 / 软件开发 / Delphi / 为钩子的下一步学习补课:如何提取32位中的某一位
为钩子的下一步学习补课:如何提取32位中的某一位2009-12-10 博客园 万一Integer 类型是 32 位的, 有 4 个字节, 现在我们需要能够提取出其 32 位中的某一位.但 Delphi 最小的整数类型也是一个字节(8位)的: Byte(无符号)、Shortint(有符号).要不先从提取一个字节开始:var
i: Integer;
b: Byte;
begin
i := MaxInt; {Integer 的最大值}
ShowMessage(IntToStr(i)); {2147483647}
{现在 i 的二进制表示是: 01111111 11111111 11111111 11111111}
{Interger 的最高位 0 表示这是个正数(1表示负数)}
{假如:}
i := 2146439167;
{现在 i 的二进制表示是: 01111111 11110000 00001111 11111111}
{现在其十六进制表示是: $7 F F 0 0 F F F }
{落实一下, 从右到左四个字节分别是: $FF、$0F、$F0、$7F }
{如果需要单独提取四个字节中的某个字节, Delphi 位我们提供了两个函数:}
b := Lo(i); {提取低位字节}
ShowMessage(Format("%.2x",[b])); {FF; 这是从右数第一个字节}
b := Hi(i); {提取高位字节}
ShowMessage(Format("%.2x",[b])); {0F; 这是从右数第二个字节}
{那么我们怎么提取第三个和第四个字节呢? 方法一:}
{右移 16 位, 然后再用 Lo 和 Hi 提取}
{01111111 11110000 00001111 11111111 右移 16 位后会变成:}
{ 01111111 11110000; 试一下:}
b := Lo(i shr 16);
ShowMessage(Format("%.2x",[b])); {F0; 这是从右数第三个字节}
b := Hi(i shr 16);
ShowMessage(Format("%.2x",[b])); {7F; 这是从右数第四个字节}
{当然 i 的第四个字节也可以这样提取:}
b := Lo(i shr 24);
ShowMessage(Format("%.2x",[b])); {7F; 这是从右数第四个字节}
{现在换个思路, 假如没有 Lo 和 Hi 函数, 我们能做到吗? 当然能:}
b := (i and $FF);
ShowMessage(Format("%.2x",[b])); {FF; 这是从右数第一个字节}
b := (i shr 8 and $FF);
ShowMessage(Format("%.2x",[b])); {0F; 这是从右数第二个字节}
b := (i shr 16 and $FF);
ShowMessage(Format("%.2x",[b])); {F0; 这是从右数第三个字节}
b := (i shr 24 and $FF);
ShowMessage(Format("%.2x",[b])); {7F; 这是从右数第四个字节}
{这是为什么? 换个语句块仔细分析}
end;
//关于上面例子的补充:
var
b: Byte;
begin
{我们知道 Byte 的最大值是 255, 也就是十六进制的 $FF, 二进制的 11111111}
{这个 $FF 有这么个特殊用途:}
b := 0 and $FF;
ShowMessage(IntToStr(b)); {0}
b := 1 and $FF;
ShowMessage(IntToStr(b)); {1}
b := 100 and $FF;
ShowMessage(IntToStr(b)); {100}
b := 255 and $FF;
ShowMessage(IntToStr(b)); {255}
{0..255 直接的任何数与 $FF 进行 and 运算后, 值不变(这从二进制的角度不难理解)}
{另外, Byte 就一个字节, 当你给它更多时, 它也只要一个字节(低位字节), 譬如:}
b := Byte(MaxInt);
ShowMessage(IntToStr(b)); {255}
{现在上面的例子应该可以理解了}
end;
回到主题://本例中我们把最低位叫第 0 位; 把 Integer 的最高位叫第 31 位.
var
i: Integer;
b: Byte;
begin
{还是用第一个例子中的值吧:}
i := 2146439167;
{现在 i 的二进制表示是: 01111111 11110000 00001111 11111111}
{一个字节的最大值是 $FF; 一个二进制位的最大值当然是 1, 写成十六进制还是 $1 }
{提取第 0 位:}
b := i and 1; ShowMessage(IntToStr(b)); {1}
{提取第 0 位也可以写作(右移0位就是没动):}
b := i shr 0 and 1; ShowMessage(IntToStr(b)); {1}
{提取第 1 位:}
b := i shr 1 and 1; ShowMessage(IntToStr(b)); {1}
{提取第 13 位:}
b := i shr 13 and 1; ShowMessage(IntToStr(b)); {0}
{提取最高位(第 31 位):}
b := i shr 31 and 1; ShowMessage(IntToStr(b)); {0}
end;
//假如只判断最高位, 是 0 还是 1(也就是判断正负), 还可以这样:
var
i: Integer;
begin
i := MaxInt; {这肯定是个正数}
if i shr 31 = 0 then ShowMessage("正"); {正}
i := -1;
if i shr 31 = 1 then ShowMessage("负"); {负}
end;