What is n= n ^1U<<i?

10

我在这里面临的问题是理解循环中每次迭代中n值的变化。
如果你可以通过2-3次迭代来解释它,那就太棒了。 更正 - 返回值应该是32位的....将所有位从0更改为1,1变为0。

long fun(long n)
{
    for(int i = 0; i < 32; i++)
        n = n ^ 1U << i;
    return n;
}   

n is a variable (argument) of type long - eerorika
2
你了解运算符优先级以及按位异或和位移操作的作用吗?那么理解它的功能应该很容易。 - Lukas-T
fun 函数的返回类型是什么?long 的大小已知吗? - Eric Postpischil
2个回答

12

i为计数器。
1U << i是一个单独的无符号位(LSB),在每个回合中向左移动i位,即它扫描位位置0001、0010、0100、1000(请读取为二进制)。
n = n ^ 1U << in设置为n和移位位的异或。也就是说,它逐位完全地对n进行异或。
结果是完全反转的n

让我们看一下在示例13(二进制中为1101)上进行4次迭代。

1101 ^ 0001 is 1100
1100 ^ 0010 is 1110
1110 ^ 0100 is 1010
1010 ^ 1000 is 0010

0010 is 1101 ^ 1111

正如Eric Postpischil所提到的:

函数的参数n是一个long,但是代码只遍历了32位中的i。它翻转了n中的低32位,而高位(如果有)则没有改变。
如果long是32位,则在某些情况下,n = n ^ 1U << i 的实现定义,因为longunsigned int的异或将导致unsigned long,并且,如果结果值不能表示为long,则结果是实现定义的。

如果我们假设适当的输入n,例如能够用32位宽类型表示,或者仅翻转较低位是有意的,则这就不是问题。
请注意,根据Eric的评论,long隐式地被视为带符号数,这意味着准 MSB并不完全可用于值表示(无论是2补数还是1补数还是符号表示),因为一半的范围用于负值。通过异或切换它可以潜在地产生奇怪的影响。


1

它将翻转n的低32位。总效果与只执行n ^= 0xFFFF相同。

在您的代码中,nlong类型。如果您使用的是32位编译器,则它将具有32位,但在其他编译器上可能会更长。

如果展开循环,您将得到以下内容:

n = n ^ 1U << 0;
n = n ^ 1U << 1;
n = n ^ 1U << 2;
...

由于<<的优先级高于^,因此结果将解析为:

n = n ^ 1;
n = n ^ 2;
n = n ^ 4;
...

最终效果是它逐位翻转32位的n

1
函数的参数n是一个long类型,但代码只迭代了32位的i。它会翻转n中的低32位,高位(如果有)则不变。 - Eric Postpischil
如果long是32位的,那么n = n ^ 1U << i在某些情况下是实现定义的,因为^操作符将longunsigned int进行运算会得到一个unsigned long,如果结果不能被表示为long,则结果是实现定义的。 - Eric Postpischil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接