在下面的代码中
int main()
{
int a = -1;
printf("%d",a>>1);
return 0;
}
为什么输出-1。
答案 0 :(得分:12)
位移仅在无符号类型上定义,对于已实现定义的有符号类型。 这是R的一个有用的改进..
严格来说,它的定义是 只要值是签名类型 积极的,结果没有 溢出,右移是 实现 - 为负面定义 值。另一方面,左移 未定义负值
┌───┬──────────────┬──────────────────────────────────┬────────────────────────┐
│ │ Unsigned │ Signed, positive │ Signed, negative │
├───┼──────────────┼──────────────────────────────────┼────────────────────────┤
│<< │ well-defined │ well-defined, except on overflow │ undefined behaviour │
│>> │ well-defined │ well-defined │ implementation-defined │
└───┴──────────────┴──────────────────────────────────┴────────────────────────┘
答案 1 :(得分:5)
因为-1是二进制的1111111 ... 111。 a>>1
操作将“签署扩展”符号位,因此您再次获得1111111 ... 111。
答案 2 :(得分:1)
大多数编译器选择将有符号数的>>
解释为算术移位。因此,由于数字最初是负数(即MSB位为1),在右移后,该位被另一个1替换以保留符号,因此,当你开始时,你最终得到-1。
答案 3 :(得分:0)
有符号值的>>
运算符可能会执行算术或逻辑移位,具体取决于编译器。算术移位保留符号位,因此-1
(在2-s补码机上,这几天是你将遇到的唯一变种)将在右移时保持-1
。 (注意,C标准明确没有指定有符号数上的>>
是算术移位还是逻辑移位。但它总是对无符号数进行逻辑移位。)
答案 4 :(得分:0)
有符号值的位移定义与实现有关。检查编译器的文档,了解它如何处理它。
答案 5 :(得分:0)
在内存中有符号整数,如果符号int存储为2的补码,当从内存{%d}读取数据时,它将转换为原始形式,因此这里2的补码-1将存储在内存中,假设整数取2个字节,所以{ {1}}
执行2's complement of -1 is 1111 1111 1111 1111
之后它会立即更改a>>1
正如我们所知,当从内存中读取数据时,它会再次转换为0补码,所以取0111 1111 1111 1111
的2的补码它就像{ {1}}等于-1
注意: 0111 1111 1111 1111
数字的2的补码与原始二进制表示2的补码相同仅适用于1000 0000 0000 0001
数字。在 C 号码中始终存储为2的补码格式