【问题标题】:How do you set only certain bits of a byte in C without affecting the rest?如何在 C 中仅设置字节的某些位而不影响其余位?
【发布时间】:2011-05-25 06:08:26
【问题描述】:

假设我有一个像 1010XXXX 这样的字节,其中 X 值可以是任何值。我想将低四位设置为特定模式,比如 1100,而高四位不受影响。我如何在 C 中以最快的速度做到这一点?

【问题讨论】:

    标签: c byte bitmask


    【解决方案1】:

    您可以通过按位与设置将所有这些位设置为 0,其中 4 位设置为 0,所有其他位设置为 1(这是设置为 1 的 4 位的补码)。然后,您可以像往常一样按位或按位。

     val &= ~0xf; // Clear lower 4 bits. Note: ~0xf == 0xfffffff0
     val |= lower4Bits & 0xf; // Worth anding with the 4 bits set to 1 to make sure no
                              // other bits are set.
    

    【讨论】:

    • 为什么 ~0xf 等于 0x0000000f(四个字节),为什么不是 3 个字节或 5 个字节?编译器是否根据要进行 ANDED 的 sizeof val 决定长度 4?
    • @doc_id:我假设 val 是一个 32 位整数。它可能是 16 位或 64 位,但不太可能是 24 或 40 位,因为它们不是标准整数类型...
    【解决方案2】:

    一般:

    value = (value & ~mask) | (newvalue & mask);
    

    mask 是一个值,所有要更改的位(并且只有它们)设置为 1 - 在您的情况下为 0xf。 newvalue 是一个包含这些位的新状态的值 - 所有其他位基本上都被忽略了。

    这适用于支持位运算符的所有类型。

    【讨论】:

    • 你能举个具体的例子吗?假设我有:n = 1024。我想将位从位置 3 更改为 7(包括,从最低有效位的 0 开始)更改为 k = 19。结果应该是:1176。我该如何实现呢?谢谢。
    • 我必须自己解决这个问题,我想出了以下宏来概括问题。 (不知道为什么代码格式化不起作用,抱歉)``` #define MASK(L,P) (~(0xffffffff > P) #define SET_VAL(BF,L,P,V) ( (BF) = ((BF) & ~MASK(L,P)) | (( (V)
    【解决方案3】:

    使用按位运算符或 |当您想将字节的位从 0 更改为 1 时。

    当您想将字节的位从 1 更改为 0 时,请使用按位运算符和 &

    例子

    #include <stdio.h>
    
    int byte;
    int chb;
    
    int main() {
    // Change bit 2 of byte from 0 to 1
    byte = 0b10101010;    
    chb = 0b00000100;       //0 to 1 changer byte
    printf("%d\n",byte);    // display current status of byte
    
    byte = byte | chb;      // perform 0 to 1 single bit changing operation
    printf("%d\n",byte);
    
    // Change bit 2 of byte back from 1 to 0
    chb = 0b11111011;       //1 to 0 changer byte
    
    byte = byte & chb;      // perform 1 to 0 single bit changing operation
    printf("%d\n",byte);
    }
    

    也许有更好的方法,我不知道。目前这会对您有所帮助。

    【讨论】:

      【解决方案4】:

      为了进一步概括给出的答案,这里有几个宏(针对 32 位值;针对不同的位域长度进行调整)。

      #include <stdio.h>
      #include <stdint.h>
      
      #define MASK(L,P)            (~(0xffffffff << (L)) << (P))
      
      #define GET_VAL(BF,L,P)      (((BF) & MASK(L,P)) >> P)
      #define SET_VAL(BF,L,P,V)    ( (BF) = ((BF) & ~MASK(L,P)) | (((V) << (P)) & MASK(L,P)) )
      
      int main(int argc, char ** argv)
      {
          uint32_t bf = 1024;
      
          printf("Bitfield before : %d , 0x%08x\n", bf, bf);
      
          
          printf("Mask(5,3): %d , 0x%08x\n", MASK(5,3), MASK(5,3));
      
      
          SET_VAL(bf,5,3,19);
          printf("Bitfield after : %d , 0x%08x\n", bf, bf);
      
          return 0;
      }
      

      顺便说一句,C 位域完全没用是荒谬的。它是满足此要求的完美语法糖,但由于将其留给每个编译器按照它认为合适的方式实现,因此对于任何实际使用都是无用的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-13
        • 1970-01-01
        • 2012-05-20
        • 2019-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多