ped*_*ram 31 c c++ bit-manipulation bitwise-operators
我们有一个整数
int x = 50;
Run Code Online (Sandbox Code Playgroud)
在二进制中,它是
00110010
Run Code Online (Sandbox Code Playgroud)
如何以编程方式更改第四(第4)位?
tem*_*def 74
除了第四位之外,您可以通过将其与除零之外的任何值进行或运算来设置数字的第四位.这可以做到
x |= (1u << 3);
Run Code Online (Sandbox Code Playgroud)
类似地,您可以通过使用除了第四位之外的任何位置的值进行AND运算来清除第四位.例如:
x &= ~(1u << 3);
Run Code Online (Sandbox Code Playgroud)
最后,您可以通过对第四位进行异或来切换,除了第四位之外,其值为零:
x ^= (1u << 3);
Run Code Online (Sandbox Code Playgroud)
要了解其工作原理,我们需要考虑两件事:
<<在这种情况下,运营商的行为是什么?在上述所有三个代码片段中,我们使用<<运算符生成一个值.的<<操作者是按位左移位运算符,它取一个值,然后它的所有比特的移位的步骤,以左侧的一些数字.在你的情况下,我用过
1u << 3
Run Code Online (Sandbox Code Playgroud)
取值1(其具有二进制表示1)然后将其所有位移位三个点,用0填充缺失值.这将创建二进制值1000,其在第四位中设置了位.
现在,为什么呢
x |= (1u << 3);
Run Code Online (Sandbox Code Playgroud)
设置数字的第四位?这与OR运算符的工作方式有关.该|=操作是像+=或者*=除了按位或-这是等同于
x = x | (1u << 3);
Run Code Online (Sandbox Code Playgroud)
那么为什么OR与x的二进制值1000设置为第四位呢?这与定义OR的方式有关:
0 | 0 == 0
0 | 1 == 1
1 | 0 == 1
1 | 1 == 1
Run Code Online (Sandbox Code Playgroud)
但更重要的是,我们可以更紧凑地重写它
x | 0 == x
x | 1 == 1
Run Code Online (Sandbox Code Playgroud)
这是一个非常重要的事实,因为它意味着对任何位进行OR运算不会改变位的值,而对任何位进行OR运算总是将该位设置为1.这意味着我们写的时候
x |= (1u << 3);
Run Code Online (Sandbox Code Playgroud)
因为除了第四位之外,(1u << 3)是一个零值,所以除了第四位之外,按位OR使x的所有位保持不变,然后将其设置为1.更一般地,对具有一系列零和1的值进行OR运算将保留位为零的所有值,并设置位为1的所有值.
现在,让我们来看看
x &= ~(1u << 3);
Run Code Online (Sandbox Code Playgroud)
这使用了按位补码运算符~,它接受一个数字并翻转其所有位.如果我们假设整数是两个字节(只是为了简单),这意味着实际的编码(1u << 3)是
0000000000001000
Run Code Online (Sandbox Code Playgroud)
当我们采用这个的补充时,我们得到数字
1111111111110111
Run Code Online (Sandbox Code Playgroud)
现在,让我们看看当我们将两个值一起按位时会发生什么.AND运算符有这个有趣的真值表:
0 & 0 == 0
0 & 1 == 0
1 & 0 == 0
1 & 1 == 1
Run Code Online (Sandbox Code Playgroud)
或者,更紧凑:
x & 0 == 0
x & 1 == x
Run Code Online (Sandbox Code Playgroud)
请注意,这意味着如果我们将两个数字组合在一起,则结果值将使所有位为0的AND-ed都设置为零,而保留所有其他位.这意味着,如果我们和
~(1u << 3)
Run Code Online (Sandbox Code Playgroud)
我们正在和
1111111111110111
Run Code Online (Sandbox Code Playgroud)
因此,通过上面的表格,这意味着"保留所有位,除了第四位,原样,然后将第四位更改为零."
更一般地说,如果要清除一组位,请创建一个数字,该数字是您希望保持位不变的任何位置,并且在您要清除位的位置为零.
最后,让我们看看为什么
x ^= (1u << 3)
Run Code Online (Sandbox Code Playgroud)
翻转数字的第四位.这是因为二进制XOR运算符有这个真值表:
0 ^ 0 == 0
0 ^ 1 == 1
1 ^ 0 == 1
1 ^ 1 == 0
Run Code Online (Sandbox Code Playgroud)
请注意
x ^ 0 == 0
x ^ 1 == ~x
Run Code Online (Sandbox Code Playgroud)
~xx的反面在哪里; 它为0表示1表示1表示0.这意味着如果我们将XOR x与值进行(1u << 3)异或运算,我们将它与XOR进行异或运算
0000000000001000
Run Code Online (Sandbox Code Playgroud)
所以这意味着"保留所有位,但第四位设置为原样,但翻转第四位." 更一般地说,如果你想翻转一些位,那么将值与一个数字进行异或,在你希望保持位完整的位置为零,而在你想要翻转这个位的位置.
希望这可以帮助!
Mar*_*k B 14
您可以随时使用std::bitset,这使得修改位变得容易.
或者您可以使用位操作(假设您的意思是第4位计数为1.如果您的意思是从0开始计数,则不要减1).请注意,我1U只是用来保证整个操作发生在无符号数字上:
设置: x |= (1U << (4 - 1));
清除: x &= ~(1U << (4 - 1));
切换: x ^= (1U << (4 - 1));
要设置第四位,请OR使用00001000(二进制).
AND用11110111(二进制)清除第四位.
XOR用00001000(二进制)切换第四位.
例子:
00110010或00001000 = 00111010
00110010 AND 11110111 = 00110010
00110010 XOR 00001000 = 00111010