zoukankan      html  css  js  c++  java
  • Delphi 中 "位" 的使用(1) 原始的二进制


    本话题涉及: 1、常用二进制的位操作; 2、集合与 "位" 的关系; 3、TBits 类.

    这里的 "位" 是指二进制位, 譬如一个 Byte 有 8 个位、一个 Integer 有 32 个位.
    在 C 语言中可以定义由 "位" 字段构成的结构体, 但因效率问题好像使用也不广泛.
    假如要保存八种状态(True/False), 最笨的办法可以使用下面的结构体:
    type
      TState = record
        b1, b2, b3, b4, b5, b6, b7, b8: Boolean;
      end;
    

    其实用 1 个字节就可以表示 8 种状态了, 因为 1 个字节就有 8 个位.
    这里是假定用每个位表示一个状态, 如果要算上各种组合这一个字节能表示 255 种情形.
    系统函数中的很多 "选项" 就是基于 "位".

    先来几个简单的关于 "位" 的练习:

    {这是查看二进制的函数}
    function ToBin(p: PByteArray; b: Integer): string;
    var
      i,j: Integer;
    begin
      Result := StringOfChar('0', b * 8);
      for i := 0 to b - 1 do for j := 0 to 7 do
        if Odd(p^[b-1-i] shr j) then Result[i*8 + 8 - j] := '1';
    end;
    
    {把一个二进制数赋给一个变量的方法}
    procedure TForm1.Button1Click(Sender: TObject);
    var
      b1,b2,b3: Byte;
    begin
      {虽 Delphi 常规下不支持二进制常量, 但其内嵌汇编支持}
      asm
        mov b1, 11100110B
      end;
      b2 := 230;
      b3 := $E6;
      {现在是给 b1 b2 b3 赋了同样的值}
      ShowMessageFmt('%d, %d, %d', [b1, b2, b3]); //230, 230, 230
    end;
    
    {使用 or 确保第二、三位是 1}
    procedure TForm1.Button2Click(Sender: TObject);
    var
      b1, b2: Byte;
    begin
      asm
        mov b1, 11100010B
        mov b2, 00000110B
      end;
      b1 := b1 or b2;
      ShowMessage(ToBin(@b1, 1)); {11100110}
    end;
    
    {使用 and 确保第二、三之外的位是 0}
    procedure TForm1.Button3Click(Sender: TObject);
    var
      b1, b2: Byte;
    begin
      asm
        mov b1, 11100010B
        mov b2, 00000110B
      end;
      b1 := b1 and b2;
      ShowMessage(ToBin(@b1, 1)); {00000010}
    end;
    
    {使用 and 探测第二、三位是否是 1}
    procedure TForm1.Button4Click(Sender: TObject);
    var
      b: Byte;
    begin
      asm mov b, 11100010B end;
      if 2 and b = 2 then ShowMessage('第二位是 1');
      {上面可以理解为: if 00000010B and b = 00000010B then ...}
      if 4 and b = 4 then ShowMessage('第三位是 1');
      {上面可以理解为: if 00000100B and b = 00000100B then ...}
    end;
    
    {使用 shr 探测第二、三位是否是 1}
    procedure TForm1.Button5Click(Sender: TObject);
    var
      b: Byte;
    begin
      asm mov b, 11100010B end;
      if Odd(b shr 1) then ShowMessage('第二位是 1');
      if Odd(b shr 2) then ShowMessage('第三位是 1');
    end;
    

    用一个 Byte 值保存八种状态的实例:

    准备工作:
    1、在空白窗体上添加 CheckListBox1;
    2、添加四个 Button, 并激活 Button1 的 OnClick 事件; 3、激活窗体的 OnCreate 事件.

    var b: Byte; {用它记录八个 CheckBox 的选择状态}
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      CheckListBox1.Items.CommaText := 'A,B,C,D,E,F,G,H';
      Button1.Caption := '保存状态';
      Button2.Caption := '恢复状态';
      Button3.Caption := '全选';
      Button4.Caption := '全不选';
      Button1.Tag := 1;
      Button2.Tag := 2;
      Button3.Tag := 3;
      Button4.Tag := 4;
      Button2.OnClick := Button1.OnClick;
      Button3.OnClick := Button1.OnClick;
      Button4.OnClick := Button1.OnClick;
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
      i: Integer;
    begin
      if TButton(Sender).Tag = 1 then b := 0;
      for i := 0 to CheckListBox1.Count - 1 do
        case TButton(Sender).Tag of
          1: if CheckListBox1.Checked[i] then b := b or (1 shl i);
          2: CheckListBox1.Checked[i] := Odd(b shr i);
          3: CheckListBox1.Checked[i] := True;
          4: CheckListBox1.Checked[i] := False;
        end;
    end;
    

    测试效果图("恢复" 写成 "回复" 了):



    "位" 操作有点抽象, 用 "集合" 代替上面的操作就简明多了; 接下来讨论 "集合" 的本质.

  • 相关阅读:
    Ant 执行 exec cmd.exe 时路径包含空格的问题
    时区时差换算(GMT,UTC,PST,PDT)
    windows 共存多个位数不同的jdk时,eclipse的报错对应措施
    Windows下查询指定端口进程,并杀死
    关于windows的jdk
    第一阶段工作总结
    mac配置git mergetool为p4merge(2013笔记整理)
    ubuntu 14.04 安装压缩包版mysql
    关于微信公众号内嵌网页的几个meta标签
    关于js的keyCode
  • 原文地址:https://www.cnblogs.com/del/p/1730115.html
Copyright © 2011-2022 走看看