我在这里面临的问题是理解循环中每次迭代中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
值的变化。
如果你可以通过2-3次迭代来解释它,那就太棒了。
更正 - 返回值应该是32位的....将所有位从0更改为1,1变为0。
long fun(long n)
{
for(int i = 0; i < 32; i++)
n = n ^ 1U << i;
return n;
}
i
为计数器。
1U << i
是一个单独的无符号位(LSB),在每个回合中向左移动i
位,即它扫描位位置0001、0010、0100、1000(请读取为二进制)。
n = n ^ 1U << i
将n
设置为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
的实现定义,因为long
与unsigned int
的异或将导致unsigned long
,并且,如果结果值不能表示为long
,则结果是实现定义的。
如果我们假设适当的输入n
,例如能够用32位宽类型表示,或者仅翻转较低位是有意的,则这就不是问题。
请注意,根据Eric的评论,long
隐式地被视为带符号数,这意味着准 MSB并不完全可用于值表示(无论是2补数还是1补数还是符号表示),因为一半的范围用于负值。通过异或切换它可以潜在地产生奇怪的影响。
它将翻转n
的低32位。总效果与只执行n ^= 0xFFFF
相同。
在您的代码中,n
是long
类型。如果您使用的是32位编译器,则它将具有32位,但在其他编译器上可能会更长。
如果展开循环,您将得到以下内容:
n = n ^ 1U << 0;
n = n ^ 1U << 1;
n = n ^ 1U << 2;
...
<<
的优先级高于^
,因此结果将解析为:
n = n ^ 1;
n = n ^ 2;
n = n ^ 4;
...
n
。n
是一个long
类型,但代码只迭代了32位的i
。它会翻转n
中的低32位,高位(如果有)则不变。 - Eric Postpischillong
是32位的,那么n = n ^ 1U << i
在某些情况下是实现定义的,因为^
操作符将long
与unsigned int
进行运算会得到一个unsigned long
,如果结果不能被表示为long
,则结果是实现定义的。 - Eric Postpischil
n
is a variable (argument) of typelong
- eerorikafun
函数的返回类型是什么?long
的大小已知吗? - Eric Postpischil