如何从变量中访问特定的位组?

我有一个“x”位的变量。 如何提取特定的一组位然后在C中处理它们?

您可以通过一系列2位按位逻辑运算来完成此操作。

[[术语MSB(msb)是最重要的位; LSB(lsb)是最不重要的位。 假设位从lsb == 0到某个msb(例如32位机器上的31)编号。 位位置i的值表示整数的2 ^ i分量的系数。]]

例如,如果你有int x ,并且想要提取某些范围的位x [msb..lsb],包括x [31..0]中的4位字段x [7..4]位,然后:

  1. 通过将x向右移位lsb位,例如x >> lsb ,可以将x的lsb位置于表达式的第0位(最低位),这是它需要的位置。

  2. 现在你必须屏蔽msb指定的任何剩余位。 这些位的数量是msb-lsb + 1.我们可以形成一个“1”位的位掩码字符串,其长度为表达式~(~0 << (msb-lsb+1)) 。 例如〜(~0 <<(7-4 + 1))==〜0b11111111111111111111111111110000 == 0b1111。

总而言之,您可以使用此表达式将所需的位向量提取为新的整数:

 (x >> lsb) & ~(~0 << (msb-lsb+1)) 

例如,

 int x = 0x89ABCDEF; int msb = 7; int lsb = 4; int result = (x >> lsb) & ~(~0 << (msb-lsb+1)); // == 0x89ABCDE & 0xF // == 0xE (which is x[7..4]) 

合理?

快乐的黑客!

如果你正在处理一个原语,那么只需使用按位运算:

 int bits = 0x0030; bool third_bit = bits & 0x0004; // bits & 00000100 bool fifth_bit = bits & 0x0010; // bits & 00010000 

如果x可以大于一个普通的原语但在编译时已知,那么你可以使用std::bitset<>来完成任务:

 #include #include // ... std::bitset<512> b(std::string("001")); b.set(2, true); std::cout << b[1] << ' ' << b[2] << '\n'; std::bitset<32> bul(0x0010ul); 

如果在编译时不知道x ,则可以使用std::vector ,然后在运行时使用位操作。 这是更多的工作,意图读取不如使用std::bitset而且速度较慢,但​​这可能是x在运行时变化的最佳选择。

 #include // ... std::vector v(256); v[2] = 1; bool eighteenth_bit = v[2] & 0x02; // second bit of third byte 

使用&,|来处理位。 <<,>>运营商。 例如,如果您的值为7(整数)并且您希望将第2位清零:

7是111

(将第2位置零,使其为101(十进制为5))

111&101 = 101(5)

这是代码:

 #include  main () { int x=7; x= x&5; printf("x: %d",x); } 

您可以使用其他运算符,如OR,向左移位,向右移位等。

您可以在联合中使用位域:

 typedef union { unsigned char value; struct { unsigned b0:1,b1:1,b2:1,b3:1,b4:1,b5:1,b6:1,b7:1; } b; struct { unsigned b0:2,b1:2,b2:2,b3:2; } b2; struct { unsigned b0:4,b1:4; } b4; } CharBits; CharBits b={0},a={0}; printf("\n%d",b.value); bbb0=1; printf("\n%d",b.value); bbb1=1; printf("\n%d",b.value); printf("\n%d",a.value); a.b4.b1=15; printf("\n%d",a.value); /* <- set the highest 4-bit-group with one statement */