我是位操作技巧的新手,我写了一个简单的代码,看看在单个数字上进行单位移位的输出。 2
#include <iostream>
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变为零)??
但是,当我将int num=2
替换为unsigned int num=2
时,我会得到相同的输出,除了
最后一个数字显示为正数,即2147483648
而不是-2147483648
我在Ubuntu Linux上使用gcc
编译器
答案 0 :(得分:16)
那是因为int
是有符号整数。在two's-complement representation中,整数的符号由最高位确定。
将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;
实际上可能go into an infinite loop on GCC。答案 1 :(得分:2)
好问题!答案很简单。
最大整数值为2^31-1
。 31(不是32)是有原因的 - 整数的最后一位用于确定它是正数还是负数。
如果你继续向左移动这个位,你最终会击中这个位并变为负值。
有关此内容的更多信息:http://en.wikipedia.org/wiki/Signed_number_representations
答案 2 :(得分:0)
一旦该位到达有符号(最高位)的符号位,它就会变为负值。