我正在制作一些基本程序,我制作了这个程序
#include<stdio.>
int main()
{
printf("%d\n",-1>>4);
return 0;
}
output = -1
我无法理解它是如何发生的?
是-1,首先补充2,然后进行移位操作,然后再进行2次补码以产生结果。
我也想知道这个输出是怎么来的
int main()
{
unsigned int a=4;
printf("%d\n",-a>>4);
return 0;
}
result = 268435455
答案 0 :(得分:4)
首先,您正在做的事情是不可移植的。
ISO C11陈述,6.5.7 Bitwise shift operators
:
E1&gt;的结果&gt; E2是E1右移E2位位置。如果E1具有无符号类型 或者如果E1具有带符号类型和非负值,则结果的值为积分 部分E1 / 2 ^ E2的商。 如果E1有签名类型和负值,则 结果值是实现定义的。
这样做是不明智的。
可能发生的事情是你有一个实现可以保留负值的符号。虽然>>
通常可以在左侧以零比特移位(并且必须为无符号或有符号非负值而这样做),但您的实现可以检测到负数并转换为一个-bits进入左起第二位,左边的位保持不变。
这意味着-1
(例如:二进制1111 1111 1111 1111
)仍然在右移之后具有该位模式。
您必须检查特定实现的文档(标准的附录J要求实现以记录他们对实现定义的行为的选择)。
您也可以使用一些更好的样本值来测试它,例如二进制1100 0000 0000 0000
右移一位,然后看看会出现什么(当然,实现说明应该是最终来源)。 / p>
举例来说,gcc
文档提供了此信息here。由于您提及使用4.6.3,因此4.6.4手册可能是最接近的。
该页面上的GCC 4.6.4 Manual (also in PDF or PostScript or an HTML tarball)
链接包含一个名为C implementation-defined behaviour
的部分,其中部分声明:
对有符号整数进行一些按位运算的结果(C90 6.3,C99 6.5)。
按位运算符作用于值的表示,包括符号和 值位,其中符号位被认为紧接在最高值之上 位。签名'&gt;&gt;'通过符号扩展对负数进行处理。
这意味着它就像我解释的那样,左边的位置和影响到第二个最左边的位:
您在以下情况下看到不同价值的原因:
unsigned int a=4;
printf("%d\n",-a>>4);
是因为-a
由于某种原因我并不完全确定,被视为-4的无符号表示。你可以看到:
#include <stdio.h>
int main()
{
unsigned int a=4;
printf("%09x\n",((unsigned int)(-a))>>1);
printf("%09x\n",(-a)>>1);
printf("%09x\n",(-((int)a))>>1);
return 0;
}
输出(注释):
07ffffffe # explicit unsigned int
07ffffffe # seemingly treated as unsigned int
0fffffffe # explicit int
我怀疑这与整数促销和ISO C11 6.5 Expressions
中详述的常规算术转换有关,但我认为这远远超出原始问题的范围
答案 1 :(得分:2)
-1具有二进制表示(假设2&#39; s补码):
11111111111111111111111111111111 // All ones, 32 of them if we assume 32 bit ints
当右移有符号数字时,如果符号位为1,则编译器似乎会移入1。
11111111111111111111111111111111 // All ones, 32 of them if we assume 32 bit ints
^^^^ These 4 are new
如您所见,数字保持不变,-1。
答案 2 :(得分:0)
-1是以位为单位的FFFFFFFF,所以当你右移任何位时它仍然是FFFFFFFF,即-1