为什么向上移位int会产生负数?
我是位操作技巧的新手,我写了一个简单的代码,看看在单个数字上进行单位移位的输出。 2
#include int main(int argc, char *argv[]) { int num=2; do { std::cout<<num<<std::endl; num=num<<1;//Left shift by 1 bit. } while (num!=0); return 0; }
输出如下。
2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216 33554432 67108864 134217728 268435456 536870912 1073741824 -2147483648
显然,连续向左移位1位,如上所述将导致零,但为什么计算机在终止循环之前输出负数(因为num变为零)?
但是,当我用unsigned int num=2
替换int num=2
,我得到相同的输出,除了最后一个数字是这个时间显示为正数,即2147483648
而不是-2147483648
我在Ubuntu Linux上使用gcc
编译器
那是因为int
是有符号整数。 在二进制补码表示中 ,整数的符号由最高位确定。
一旦你将1移到最高(符号)位,它就会翻转为负数。
使用unsigned
,没有符号位。
0x80000000 = -2147483648 for a signed 32-bit integer. 0x80000000 = 2147483648 for an unsigned 32-bit integer.
编辑:
请注意,严格来说,有符号整数溢出是C / C ++中未定义的行为。 GCC在这方面的行为并不完全一致:
-
num = num << 1;
或者num <<= 1;
通常表现如上所述。 -
num += num;
或num *= 2;
实际上可能会进入GCC的无限循环 。
好问题! 答案很简单。
最大整数值为2^31-1
。 31(不是32)是有原因的 – 整数的最后一位用于确定它是正数还是负数。
如果你继续向左移动位,你最终会击中这一位并且它变为负数。
有关此内容的更多信息: http : //en.wikipedia.org/wiki/Signed_number_representations
一旦该位到达有符号(最高有效位)的符号位,它就会变为负数。