【问题标题】:Function accepting two arguments, a byte and a bit field, and returns the value of the field in the byte函数接受两个参数,一个字节和一个位字段,并返回字节中字段的值
【发布时间】:2011-06-09 15:35:50
【问题描述】:

我在网上找到了一些执行此任务的代码:

byte = byte >> field;
byte = byte & 0x01;
return(byte);

但是,我不明白为什么我们不能这样做:

return(byte & field);

这行得通吗?为什么或者为什么不?有更好的实现吗?

【问题讨论】:

  • 如果你一个一个地得到所有位,那么应用于字段的序列是 (0,1,2,3,4,5,6,7,8,9...) 还是(0,1,2,4,8,16,32,64...)?

标签: c++ c bit-fields


【解决方案1】:

第一个相当于:

return (byte >> field) & 0x01;

它真正做的是转移到位置为field 的位,如果该位被设置则返回1,否则返回0

您建议的不正确,因为它没有转移到指定字段的偏移量。例如,byte & 5 没有任何意义。

函数也可以这样写:

return byte & (1 << field);

当然,如果您打算将1 &lt;&lt; 5 传递给它而不是5,您可以按照自己的方式编写。

我想field 是一个数字,表示我们感兴趣的位的位置,因此对于单个字节,它将在0..7 范围内。

【讨论】:

  • 您的第二个示例的工作方式并不完全相同 - 它不是返回01,而是返回01 &lt;&lt; field
【解决方案2】:

在第一个代码示例中,field 是您想要其值的字段中位的位置。

在第二个示例中,字段必须是该位设置为 1 的 int,即 1 &lt;&lt; field

【讨论】:

    【解决方案3】:

    如果你真的希望返回值为零或一,你可以

    return ((byte & (1 << field)) != 0);
    

    return ((byte >> field) & 0x01);
    

    如果您关心的只是返回值是零还是非零,那么这两种形式都会简化一点。

    【讨论】:

      【解决方案4】:

      字节右移

      field 表示您从右侧 (LSB) 获得的字的位数。 byte = byte &gt;&gt; field 会将字节byte 的位号field 带到LSB 位置。然后byte = byte &amp; 0x01 将字节与0x01 相乘,这意味着如果它最初在位号field 中设置了位,则结果将在LSB 中包含1,或者如果它具有0,则将包含0在那个位置清零。

      例如,需要检查字节0x52 是否设置了其位号4 的测试如下所示。

          byte   = 0x52 =  0 1 0 1 0 0 1 0
      
          field  = 0x04 =  0 0 0 0 0 1 0 0
      
          Operation: byte = byte >> field
      
          The bit number 4 is single quoted below. Note how it moves
      
                                        intermediate byte       | lost bits during
                                              states            | right shifting
      
          byte         = 0x52         = 0  1  0 '1' 0  0  1  0  |
          shift 1      = 0x29         = 0  0  1  0 '1' 0  0  1  | 0
          shift 2      = 0x14         = 0  0  0  1  0 '1' 0  0  | 1 0
          shift 3      = 0x0A         = 0  0  0  0  1  0 '1' 0  | 0 1 0
          shift 4      = 0x05         = 0  0  0  0  0  1  0 '1' | 0 0 1 0
      
          Note that the bit 4 is now moved at the LSB/righ most position of the byte
          now if we test the rightmost position of the above byte then we can check
          if the bit number 4 had its bit set or cleared, with the following operation
      
          Operation: byte = byte & 0x01
      
          byte is now 0x05
      
          byte         = 0x05  = 0 0 0 0 0 1 0 '1'
          AND                    & & & & & & &  &
                         0x01  = 0 0 0 0 0 0 0  1
                         ----    ----------------
                         0x01    0 0 0 0 0 0 0  1
      
         Now byte contains 0x01 so bit number 4 had the bit set. In the other case the
         final answer would be 0.
      

      但是我们不能使用byte &amp; field 来检查编号为field 的位是否设置或清除。这是因为field 只是一个二进制文件而不是掩码。如果我们执行byte &amp; field,则会发生以下情况。

        byte         = 0x52  = 0 1 0 1 0 0 1 0
        AND                    & & & & & & & &
        field        = 0x04  = 0 0 0 0 0 1 0 0
                       ----    ---------------
                       0x00    0 0 0 0 0 0 0 0
      

      field 的值为0x04,即其位号2 已设置。通过这个操作,我们实际检查了比特号2 是否被设置。如果field 的值为5,则将设置位02,因此如果提取位02byte,可以有四种可能的组合。

      0x01 左移并制作掩码

      测试byte 的位值的其他方法不是移动byte 本身,而是将0x01 掩码field 向左移动几次,然后将其与字节进行AND,并检查是否是否为零。 (byte &amp; (0x01 &lt;&lt; field)) != 0 将在设置了 field 编号位时为真,否则为假。

         Operation: (0x01 << field)
      
            Shifting 0x01 to the left field times field = 0x04 for the example
      
                       = 0x01             = 0 0 0 0 0 0 0 1  
          shift 1      = 0x02             = 0 0 0 0 0 0 1 0
          shift 2      = 0x04             = 0 0 0 0 0 1 0 0
          shift 3      = 0x08             = 0 0 0 0 1 0 0 0
          shift 4      = 0x10             = 0 0 0 1 0 0 0 0
      
      
            After the left shift the '1' moves in the bit position 4
            Now we AND this with the byte to check if the bit position 4
            is set or clear.
      
        byte            = 0x52  = 0 1 0 1 0 0 1 0
        AND                       & & & & & & & &
        (0x01 << field) = 0x10  = 0 0 0 1 0 0 0 0
                          ----    ---------------
                          0x10    0 0 0 1 0 0 0 0
      
        Therefore the answer (0x01 != 0) is 1 there fore the bit 4 is set. It the bit 4
        was not set then the answer would be 0.
      

      使用预计算掩码

      如果您有一个需要定期测试的特定格式的字节,例如某个预定义字的某个位域,其中每个位表示某些特定的东西,那么您可以保留预计算机掩码,它仅在特定的将使用该掩码进行测试的位位置。例如,要检查一个字节,预计算机掩码将是:

      #define BIT_0 0x01 //(00000001)
      #define BIT_1 0x02 //(00000010)
      #define BIT_2 0x04 //(00000100)
      #define BIT_3 0x08 //(00001000)
      #define BIT_4 0x10 //(00010000)
      #define BIT_5 0x20 //(00100000)
      #define BIT_6 0x40 //(01000000)
      #define BIT_7 0x80 //(10000000)
      

      所以要测试 byte 中的第 4 位,我们必须执行 return (byte &amp; BIT_4)return (byte &amp; BIT_4) != 0;

      根据位位置代表的宏名称可以设置。

      【讨论】:

        【解决方案5】:

        第一个示例将所需的位移动到返回的 LSB,但第二个示例只是屏蔽了所有不需要的位。

        【讨论】:

          【解决方案6】:

          这可以由结构给出。让我们说:

          struct POWERTRAIN_ERROR 
          {
          
              uint8 ERROR_CODE;
          
              unit8 LAMP_STATUS : 1;
              };
          
              struct POWERTRAIN_ERROR   pt_error;
          
              uint8 func ( struct POWERTRAIN_ERROR pt)
          
              {
          
              // do something with pt.ERROR_CODE (which is a byte) and pt.LAMP_STATUS which is a bit field
          
              // lets say, this function needs to return the status of 0th bit of ERROR_CODE 
          
              return ( pt.ERROR_CODE & 0x1) ;
          
          }
          

          【讨论】:

            猜你喜欢
            • 2016-01-07
            • 2015-04-02
            • 2022-11-15
            • 2017-03-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-05-13
            相关资源
            最近更新 更多