改变一个整数

时间:2011-08-02 18:45:06

标签: c++ c bit-manipulation bitwise-operators

我们有一个整数

int x = 50;

在二进制文件中,它是

00110010

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

6 个答案:

答案 0 :(得分:71)

您可以通过将数字的第四位与除第四位之外的任何位置的值进行或运算来设置它的第四位。这可以作为

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

类似地,您可以通过使用除了第四位之外的任何位置的值进行AND运算来清除第四位。例如:

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

最后,您可以通过对第四位进行异或来切换,除了第四位之外,其值为零:

x ^= (1u << 3);

要了解其原因,我们需要考虑两件事:

  1. 此上下文中<<运算符的行为是什么?
  2. 这里的AND,OR和XOR运算符的行为是什么?
  3. 在上述所有三个代码段中,我们使用<<运算符生成值。 <<运算符是按位左移运算符,它接受一个值,然后将其所有位向左移动一些步骤。在你的情况下,我用

    1u << 3
    

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

    现在,为什么

    x |= (1u << 3);
    

    设置数字的第四位?这与OR运算符的工作方式有关。 |=运算符与+=*=类似,但按位OR除外 - 它相当于

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

    那么为什么OR与x和二进制值1000设置其第四位?这与定义OR的方式有关:

    0 | 0  == 0
    0 | 1  == 1
    1 | 0  == 1
    1 | 1  == 1
    

    更重要的是,我们可以更紧凑地重写这个

    x | 0  == x
    x | 1  == 1
    

    这是一个非常重要的事实,因为它意味着对任何位进行OR运算不会改变位的值,而对任何位进行OR运算总是将该位设置为1。这意味着我们写的时候

    x |= (1u << 3);
    

    因为(1u <&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&#;&gt更一般地,对具有一系列零和1的值进行OR运算将保留位为零的所有值,并设置位为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
    

    请注意,这意味着如果我们将两个数字组合在一起,则结果值将使所有位为0的AND-ed都设置为零,而保留所有其他位。这意味着如果我们和

    ~(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)进行异或运算,我们将其与

    进行异或运算
    0000000000001000
    

    所以这意味着“保留所有位,但第四位按原样设置,但翻转第四位。”更一般地说,如果你想翻转一些位,那么将值与一个数字进行异或,使得你想要保持位完整的数字为零,并且你想要翻转这个位。

    希望这有帮助!

答案 1 :(得分:13)

您始终可以使用std::bitset来简化修改位。

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

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

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

要切换:x ^= (1U << (4 - 1));

答案 2 :(得分:7)

要设置第四位OR00001000(二进制)。

使用AND(二进制)清除第四位11110111

使用XOR(二进制)切换第四位00001000

示例:

  

00110010 OR 00001000 = 00111010

     

00110010 AND 11110111 = 00110010

     

00110010 XOR 00001000 = 00111010

答案 3 :(得分:2)

简单,因为你拥有或拥有任何价值,

int x = 50;

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

int y = x | 0x00000008;

因为0x在数字之前加上前缀意味着它的十六进制形式。 因此,0x0 = 0000为二进制,0x8=1000为二进制形式。 这解释了答案。

答案 4 :(得分:1)

在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;
}

答案 5 :(得分:0)

您可以使用二进制AND和OR来切换第四位。

要设置x上的第四位,您将使用x |= 1<<3;1<<3左移0b0001三位产生0b1000。

要清除x上的第四位,您将使用x &= ~(1<<3);,在0b00110010(x)和(有效)0b11110111之间的二进制AND,屏蔽x中不在第四位的每个位,从而清除它