【问题标题】:Bit Manipulation Delphi in XML - BitwiseXML 中的位操作 Delphi - 按位
【发布时间】:2013-01-23 18:40:35
【问题描述】:

我是一名高中生,目前正在学习 Delphi XE3。我们正在学习 BIT 操作。我们有一个任务,虽然我已经阅读了很多关于该主题的内容并了解在 Bits 和 SHL/SHR 中存储信息的整个过程,但我很难理解如何在 Delphi 中执行此过程。

作业如下:

Decimal        Hexidecimal    Binary
1              0x0001         0000000000000001
2              0x0002         0000000000000010
4              0x0004         0000000000000100

在 XML 文件中传递一个整数值来标识选项集。例如。如果我想发送选项 1 和选项 2,我会添加 1+2=3。我会发送 3 作为数字来指定选项 1 和 2 为真。

在客户端,二进制值为 0000000000000011 = 3

根据我的阅读,我需要使用面具,但我不明白如何做到这一点。我如何在 Delphi 中使用掩码来获取 True 或 False 的各个值。

我尝试在常规 Integer 变量中执行此操作,但它总是被视为 Integer,结果非常奇怪。如果我将整数转换为二进制字符串表示并遍历字符,则结果是正确的,但我假设我不应该对字符串执行此操作。任何帮助或示例将不胜感激。谢谢。

【问题讨论】:

  • 请你问一个具体的问题。这里没有。
  • 我想了解如何读取是否从整数值设置了特定位以及如何设置特定位。如果值为 1 + 4 = 5,那么我如何读取右侧的 1 和 3 位是否设置或等于 True。
  • 嗯,我们通常从 0 开始对位进行编号。因此,您将测试位 0 和 2。为此,您为位 0 编写 (x and 1)<>0,为位 2 编写 (x and 4)<>0。您应该更直接地问这个问题。
  • X 是常规整数还是字节变量?
  • @DavidHeffernan,谢谢。我将 SHL 和 SHR 用于什么用途?

标签: delphi delphi-xe2 bit-manipulation


【解决方案1】:

您通常使用and 二元运算符检查整数变量中是否设置了特定位,然后使用or 运算符设置各个位,如下所示:

const
  OPTION_X = $01;
  OPTION_Y = $02;
  OPTION_Z = $04;

var
  Options: Byte;
begin
  Options := OPTION_X or OPTION_Y;  //actually 3, like in your example
  //check if option_X is set
  if (Options and OPTION_X) = OPTION_X then
    ShowMessage('Option X is set');  //this message is shown, because the bit is set
  //check if option_Z is set
  if (Options and OPTION_Z) = OPTION_Z then
    ShowMessage('Option Z is set');  //this message is NOT shown
end;

不同的OPTION_ 常量实际上是masks,在某种意义上它们用于将位掩码为零(以检查是否设置了特定位)或将​​位掩码为1(以设置特定位) .

考虑这个片段:

begin
  ..

  if cbOptionX.Checked then
    Options := Options or OPTION_X;
  ..

or 会将第一位掩码为 1。如果我们从选项值(二进制)01010000 开始,生成的选项将为 01010001

    01010000   
 OR 00000001  //OPTION_X 
  = 01010001   

使用相同的值将所有其他位屏蔽为 0,以检查是否设置了特定位。 if 条件,例如:(Options and OPTION_Z) = OPTION_Z,这样做:

  • 首先它将Option变量的所有不感兴趣的字节掩码为0。如果我们考虑最后一个值01010001,该操作将导致清除所有位,但第一个。

        01010001   
    AND 00000001   
      = 00000001   
    

考虑到 01010000 的起始值,它将返回零:

        01010000   
    AND 00000001   
      = 00000000   
  • 接下来,它比较该值是否等于掩码本身。如果相等,则在原始 Options 变量中设置该位,否则未设置。如果您的掩码仅包含一位,那是口味问题,您可以检查结果值是否例如不同于 0,但如果您的掩码包含多个位并且您想检查是否设置了所有位,您必须检查是否相等。

【讨论】:

  • 虽然所有答案都有帮助,而且 UWA Rabee 给出了最简单的答案,但我需要了解口罩的概念。 @jachguate,非常感谢。比我想象的要简单得多。
  • 测试 0 更好,因此避免违反 DRY
  • 我阅读了测试单个位的代码。我的评论适用。
  • @jachguate,我可以在一次操作中检查多个位吗?
  • @LHearn 你是否看起来不错。为什么要遍历所有位值?
【解决方案2】:

Delphi 有一个预定义的类型 TIntegerSet,它允许使用集合运算符。假设options 是一个整数,您可以检查是否有任何位(从 0 开始)设置如下:

option1 := 0 in TIntegerSet(options); { Bit 0 is set? }
option3 := 2 in TIntegerSet(options); { Bit 2 is set? }

通过包含或排除更改选项:

Include(TIntegerSet(options), 0); { set bit 0 }
Exclude(TIntegerSet(options), 2); { reset bit 2 }

当然,您可以使用任何其他可能有用的集合运算符。

【讨论】:

    【解决方案3】:

    Delphi 有 位运算符 用于操作整数类型的各个位。查看shlshrandorxor 运算符。要组合位,请使用 or 运算符。要测试位,请使用 and 运算符。例如,假设这些常量:

    const
      Option1 = 0x0001;
      Option2 = 0x0002;
      Option3 = 0x0004;
    

    or 运算符查看两个输入值的位,并在任一输入值具有1 位的位置生成具有1 位的输出值。所以组合位看起来像这样:

    var
      Value: Integer;
    begin
      Value := Option1 or Option2;
      {
      00000000000000000000000000000001 Option1
      00000000000000000000000000000010 Option2
      -------------------------------- OR
      00000000000000000000000000000011 Result
      }
      ...
    end;
    

    and 运算符查看两个输入值的位,并仅在两个输入值都具有1 位的地方生成具有1 位的输出值,否则它会生成0 位反而。所以比特测试看起来像这样:

    var
      Value: Integer;
      Option1Set: Boolean;
      Option2Set: Boolean;
      Option3Set: Boolean;
    begin
      Value := 7; // Option1 or Option2 or Option3
    
      Option1Set := (Value and Option1) = Option1;
      {
      00000000000000000000000000000111 Value
      00000000000000000000000000000001 Option1
      -------------------------------- AND
      00000000000000000000000000000001 Result
      }
    
      Option2Set := (Value and Option2) = Option2;
      {
      00000000000000000000000000000111 Value
      00000000000000000000000000000010 Option2
      -------------------------------- AND
      00000000000000000000000000000010 Result
      }
    
      Option3Set := (Value and Option3) = Option3;
      {
      00000000000000000000000000000111 Value
      00000000000000000000000000000100 Option3
      -------------------------------- AND
      00000000000000000000000000000100 Result
      }
      ...
    end;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多