【发布时间】:2011-07-25 12:23:08
【问题描述】:
在下面这段代码中
int main()
{
int a = -1;
printf("%d",a>>1);
return 0;
}
为什么它给出输出 -1。
【问题讨论】:
-
看到这个问题shift operator in C。
标签: c
在下面这段代码中
int main()
{
int a = -1;
printf("%d",a>>1);
return 0;
}
为什么它给出输出 -1。
【问题讨论】:
标签: c
位移位仅在无符号类型上定义,对于有符号类型,它是实现定义的。 这是 R.. 的有用改进。
严格来说,它被定义为 有符号类型,只要值是 阳性,结果不 溢出,右移是 实现定义为负 价值观。另一方面,左移, 对于负值是未定义的
┌───┬──────────────┬──────────────────────────────────┬────────────────────────┐
│ │ Unsigned │ Signed, positive │ Signed, negative │
├───┼──────────────┼──────────────────────────────────┼────────────────────────┤
│<< │ well-defined │ well-defined, except on overflow │ undefined behaviour │
│>> │ well-defined │ well-defined │ implementation-defined │
└───┴──────────────┴──────────────────────────────────┴────────────────────────┘
【讨论】:
因为 -1 在二进制中是 1111111...111。 a>>1 操作将“符号扩展”符号位,因此您再次获得 1111111...111。
【讨论】:
大多数编译器选择将有符号数上的>> 解释为算术移位。因此,由于该数字最初为负数(即 MSB 位为 1),在右移后,该位被另一个 1 替换以保留符号,因此您开始时会得到 -1。
【讨论】:
有符号值上的>> 运算符可以执行算术或逻辑移位,具体取决于编译器。算术移位保留符号位,因此-1(在 2-s 补码机器上,这几天几乎是您会遇到的唯一变化)在右移时将保持 -1。 (请注意,C 标准没有明确指定有符号数上的 >> 是算术移位还是逻辑移位。不过,它始终是无符号数上的逻辑移位。)
【讨论】:
有符号值移位的定义取决于实现。检查编译器的文档以了解其处理方式。
【讨论】:
在内存中,如果有符号整数,则存储为 2 的补码,当从内存 {%d} 读取数据时,它会转换为原始形式,所以这里 -1 的 2 的补码将存储在内存中,假设整数占用 2 个字节,所以 @ 987654321@
在执行a>>1 之后,它现在会改变0111 1111 1111 1111 我们知道,当从内存中读取数据时,它会再次转换为0 补码,所以取0111 1111 1111 1111 的2 的补码,它就像1000 0000 0000 0001 等于-1
注意: +ve 数的 2 补码与原始二进制表示相同 2 的补码仅适用于 -ve 数。在 C 中,数字始终存储为 2 的补码形式
【讨论】:
%u 打印,你得到了一个未定义的行为