C++长整数位运算结果解释差异及原理问询
你的C++位操作疑问详解
1. 原代码的位操作到底做了什么?
先拆解原代码里的核心循环:
int x=32; long long t=1; while(x--){ n=(n^t); t=t<<1; }
这个循环的本质是对n的低32位逐位取反,而long long的高位(第32到63位)完全保持不变。原因很直观:
t从1(对应二进制最低位,2^0)开始,每次左移1位,循环32次后,会依次覆盖2^0到2^31的所有低32位。- 每一次
n ^ t操作,都会把n中对应t为1的那一位翻转(0变1,1变0)。 - 32次循环后,
n的低32位每一位都被翻转了一遍,高位因为没被t触碰到,所以和初始值一致。
比如输入2147483647(也就是0x7FFFFFFF,低31位全1,第31位是0),循环后低32位变成0x80000000,高位还是0,最终n的值是0x0000000080000000——因为long long的符号位是第63位(这里是0),所以输出正数2147483648。
2. 为什么原代码输出是大正数,而~取反却输出负数?
这不是因为被解释成了不同类型,而是两者的二进制结果完全不同:
- 原代码只翻转低32位,高位保留。只要
long long的第63位(符号位)是0,输出就会是正数。比如输入0,翻转低32位后得到0x00000000FFFFFFFF,符号位为0,所以输出4294967295(2^32-1)。 - 而
~n是对n的所有64位取反(因为n是long long类型)。比如输入2147483647(0x000000007FFFFFFF),~n的结果是0xFFFFFFFF80000000,此时第63位是1(符号位为1),作为有符号整数就会被解释为负数-2147483648。
简单说:原代码是“半取反”(仅低32位),~是“全取反”(所有位),二进制值天差地别,输出自然不同。
3. 替换long long为long后结果一致的原因
在当前主流的64位操作系统(Windows 64位、Linux、macOS)中,long和long long都是64位有符号整数类型,它们的内存布局、取值范围完全一致。所以把代码里的long long换成long后,位操作的逻辑没有变化,二进制结果也完全相同,输出自然一致。
如果是在老旧的32位系统中,long是32位有符号整数,替换后结果会不一样,但现在32位系统已经非常少见了。
补充:为什么你会觉得“按常理结果应为负数”?
你可能误以为原代码是对整个long long取反,但实际上它只操作了低32位。你的输入都是低32位的数(高位全0),操作后高位还是0,符号位始终为0,所以永远不会输出负数。只有当n的高位原本有1,操作后符号位变成1时,才会输出负数。
内容的提问来源于stack exchange,提问作者Sannidhi Kumar
相关产品推荐
相关产品推荐

