改变一个整数的位

Change a bit of an integer

本文关键字:整数 一个 改变      更新时间:2023-10-16

我们有一个整数

int x = 50;
二进制的

就是

00110010

如何以编程方式更改第四(第4)位?

您可以通过将一个数字与除第4位以外的其他位置的值进行or运算来设置数字的第4位。这可以通过

x |= (1u << 3);

同样,可以用除第四个位以外的所有位置都为1的值进行与运算来清除第四个位。例如:

x &= ~(1u << 3);

最后,您可以通过将第四个位与除第四个位以外的其他位置的值进行异或运算来切换第四个位:

x ^= (1u << 3);

要了解为什么会这样,我们需要看两件事:

  1. 在这种情况下,<<操作符的行为是什么?
  2. 这里的AND, OR和异或操作符的行为是什么?

在上面的三个代码片段中,我们使用<<操作符来生成一个值。<<运算符是位左移运算符,它取一个值,然后将它的所有位向左移若干步。在你的例子中,我使用

1u << 3

取值1(其二进制表示为1),然后将其所有位移动三个位置,用0填充缺失的值。这将创建二进制值1000,它在第四个位上设置了一个位。

为什么

x |= (1u << 3);

设置数字的第4位?这与OR运算符的工作方式有关。|=运算符类似于+=*=,除了位或运算符——它相当于

x = x | (1u << 3);

那么为什么用二进制值1000对x进行or运算来设置它的第4位呢?这与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);

since (1) <<3)是一个除了第四个位以外的所有地方都为零的值,按位或使x的所有位保持不变,除了第四个位,然后将其设置为1。更一般地说,对一个由0和1组成的数字进行or运算,将保留位为0的所有值,并设置位为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

因此,根据我们上面的表,这意味着"保留所有的位,除了第四个位,保持原样,然后将第四个位改为零。"

更一般地说,如果你想要清除一组位,在你想要保持位不变的地方创建一个1,在你想要清除位的地方创建一个0。

最后,让我们看看为什么

x ^= (1u << 3)

翻转数字的第4位。这是因为二进制异或运算符有这样一个真值表:

0 ^ 0  == 0
0 ^ 1  == 1
1 ^ 0  == 1
1 ^ 1  == 0

注意

x ^ 0  == 0
x ^ 1  == ~x

其中~x为x的对立面;1等于0,0等于1。这意味着如果我们将x与值(1u << 3)进行异或,我们将与

进行异或
0000000000001000

所以这意味着"保持除第4位以外的所有位不变,但翻转第4位。"更一般地说,如果你想要翻转一些位,把这个值与一个数字进行异或,在这个数字中,你想要保持这些位的完整性,而在你想要翻转这些位的地方,这个数字是0。

希望这对你有帮助!

您始终可以使用std::bitset,这使得修改位容易。

或者您可以使用位操作(假设您的意思是计数为1的第4位)。请注意,我使用1U只是为了保证整个操作发生在无符号数上:

设置:x |= (1U << (4 - 1));

清除:x &= ~(1U << (4 - 1));

To toggle: x ^= (1U << (4 - 1));

设置第4位,OR00001000(二进制)。

11110111(二进制)清除第4位AND

XOR00001000(二进制)交换。

例子:

00110010 OR 00001000 = 00111010

00110010 AND 11110111 = 00110010

00110010 XOR 00001000 = 00111010

很简单,因为你有,或者不管你有什么值

int x = 50;

以编程方式设置第4位(从右开始),

int y = x | 0x00000008;

因为,0x前缀在数字前表示它是十六进制形式。所以,0x0 = 0000是二进制的,0x8=1000是二进制的。这就解释了答案。

在C语言中试试这些函数中的一个来改变n位

char bitfield;
// start at 0th position
void chang_n_bit(int n, int value)
{
    bitfield = (bitfield | (1 << n)) & (~( (1 << n) ^ (value << n) ));
}
void chang_n_bit(int n, int value)
{
    bitfield = (bitfield | (1 << n)) & ((value << n) | ((~0) ^ (1 << n)));
}
void chang_n_bit(int n, int value)
{
    if(value)
        bitfield |= 1 << n;
    else
        bitfield &= ~0 ^ (1 << n);
}
char print_n_bit(int n)
{
    return (bitfield & (1 << n)) ? 1 : 0;
}

可以使用二进制的AND和OR来切换第4位

要设置x上的第4位,可以使用x |= 1<<3;, 1<<3左移0b0001 3位,产生0b1000。

要清除x上的第四个位,您可以使用x &= ~(1<<3);,这是0b00110010 (x)和(有效地)0b11110111之间的二进制与,屏蔽掉x中不在第四个位置的每个位,从而清除它。

相关文章: