随笔 - 2146  文章 - 97 评论 - 11767 trackbacks - 253

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;

posted on 2008-02-27 22:28  万一  阅读(...)  评论(...编辑  收藏