改变一个整数的位
这个问题在这里已经有了答案:
您可以设置数字的第四位,除了第四位以外,其它位置的值都是零。 这可以做到
x |= (1u << 3);
同样,可以通过将第四位与除第四位以外的值进行AND来清除第四位。 例如:
x &= ~(1u << 3);
最后,可以通过将第四位与第四位中除零以外的值进行异或来切换第四位:
x ^= (1u << 3);
要明白为什么这会起作用,我们需要看两件事情:
<<
运算符的行为是什么? 在上述所有三个代码片段中,我们使用<<
运算符来生成一个值。 <<
运算符是按位左移运算符,它取一个值,然后将其所有位向左移动一些步数。 就你而言,我用过
1u << 3
取值1(其具有二进制表示1),然后将所有比特移位三个点,用0填充缺失值。这产生了二进制值1000
,其在第四比特中设置了比特。
现在,为什么
x |= (1u << 3);
设置数字的第四位? 这与OR运算符的工作方式有关。 |=
运算符类似于+=
或*=
除了按位或 - 它相当于
x = x | (1u << 3);
那么为什么用二进制值1000
对OR进行求和呢? 这与OR的定义方式有关:
0 | 0 == 0
0 | 1 == 1
1 | 0 == 1
1 | 1 == 1
但更重要的是,我们可以更简洁地将其重写为
x | 0 == x
x | 1 == 1
这是一个非常重要的事实,因为它意味着将任意位与0或不改变该位的值,而将任何位与1进行或运算总是将该位设置为1。 这意味着,当我们写作
x |= (1u << 3);
由于(1u << 3)是除第四位之外的任何地方都为零的值,所以按位OR将除了第四位之外保持x的所有位不变,然后将其设置为1。 更一般地说,将一个数字与一系列零和一个数值进行或运算,将保留所有位为零的值并设置位为1的所有值。
现在,让我们看看
x &= ~(1u << 3);
这使用了按位补码运算符~
,它取一个数字并翻转所有位。 如果我们假设整数是两个字节(为了简单起见),这意味着(1u << 3)
的实际编码是
0000000000001000
当我们补充这个时,我们得到这个数字
1111111111110111
现在,让我们看看当我们将两个值按位与两个值合并时会发生什么。 AND运算符有这个有趣的真值表:
0 & 0 == 0
0 & 1 == 0
1 & 0 == 0
1 & 1 == 1
或者更简洁:
x & 0 == 0
x & 1 == x
请注意,这意味着如果我们将两个数字组合在一起,则所得到的值将会使得所有与零相关的位被设置为零,而所有其他位都被保留。 这意味着如果我们和与
~(1u << 3)
我们正在与
1111111111110111
所以通过我们上面的表格,这意味着“保留所有的位,除了第四位之外,然后将第四位更改为零。”
更一般地说,如果你想清除一组比特,那么创建一个你希望保持比特不变的数字,在你想清除比特的地方创建一个数字。
最后,让我们看看为什么
x ^= (1u << 3)
翻转数字的第四位。 这是因为二元XOR运算符有这个真值表:
0 ^ 0 == 0
0 ^ 1 == 1
1 ^ 0 == 1
1 ^ 1 == 0
注意到
x ^ 0 == 0
x ^ 1 == ~x
其中~x
是x的相反; 0代表1,1代表0。这意味着如果我们将XOR x与值(1u << 3)
异或运算,我们将它与XOR
0000000000001000
所以这意味着“保留所有的位,但是第四位按原样设置,但是翻转第四位”。 更一般地说,如果你想翻转一些位数,把数值与一个数字进行异或,这个数字在你想保持这些位完好无损的地方,以及一个你想要翻转这些位的地方。
希望这可以帮助!
您始终可以使用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和11110111 = 00110010
00110010 XOR 00001000 = 00111010
链接地址: http://www.djcxy.com/p/28787.html