我已经编写了这个程序作为练习来理解有符号和无符号整数
在C.工作
此代码应仅打印-9
添加-4+-5
存储在变量c
#include <stdio.h>
int main (void) {
unsigned int a=-4;
unsigned int b=-5;
unsigned int c=a+b;
printf("result is %u\n",c);
return 0;
}
当此代码运行时,它会给我一个意外的结果4294967287
。
我还从c
投了unsigned
到signed integer
printf ("result is %u\n",(int)c);
但也没有用。
请有人解释为什么程序没有给出确切的结果?
答案 0 :(得分:2)
如果这是c中的练习而且签名vs unsigned你应该从思考开始 - 这是什么意思?
unsigned int a=-4;
它应该编译吗?这似乎是一个矛盾。
使用调试器检查存储在a位置的内存。你认为在这种情况下它会是一样的吗?
int a=-4;
当编译器要求将unsigned x添加到unsigned y而不是signed x和signed y时,编译器是否会执行不同的操作。让编译器向您展示它在每种情况下生成的机器代码,阅读说明中的内容
探索调查验证,您有机会获得有关计算机真正工作方式的真正有趣的见解
答案 1 :(得分:1)
你期待这个:
printf("result is %u\n",c);
打印-9
。这是不可能的。 c
类型为unsigned int
,%u
打印类型unsigned int
的值(使用正确的格式字符串作为参数)。 unsigned int
对象无法存储负值。
回到你的计划中的几行:
unsigned int a=-4;
4
属于(签名)int
类型,具有明显的价值。将一元-
应用于该值会产生int
-4
的值。
到目前为止,非常好。
现在将这个负int
值存储在unsigned int
对象中会发生什么?
已转换。
该语言指定将已签名的int
值转换为unsigned int
时会发生什么:将值调整为unsigned int
范围内的值。如果unsigned int
是32位,则可以根据需要多次添加或减去2 32 来完成。在这种情况下,结果是-4 + 2 32 或4294967292
。 (如果用十六进制显示它,那么这个数字会更有意义:0xfffffffc
。)
(生成的代码不是真的将重复添加或减去2 32 ;它会做任何它需要做的事情得到相同的结果。使用两个补码表示有符号整数的一个很酷的事情是,它不必做任何。int
值{{ 1}}和-4
值unsigned int
具有完全相同的位表示。规则是根据值定义的,但它们的设计使得它们可以使用按位运算轻松实现。 )
同样,4294967292
的值为-5 + 2 32 或c
。
现在将它们添加到一起。 数学结果为4294967291
,但不适合8589934583
。使用与转化相似的规则,结果会降低到unsigned int
范围内的值,产生unsigned int
(或十六进制,4294967287
)。< / p>
您还尝试过演员:
0xfffffff7
您已将printf ("result is %u\n",(int)c);
参数传递给int
,但您已告知(使用printf
)期望%u
。您还尝试转换的值过大而不适合unsigned int
- 并且未签名到签名的转换规则不会定义此类转换的结果超出范围。所以不要这样做。
答案 2 :(得分:0)
对于32位整数,这个答案是完全正确的。
unsigned int a = -4;
将a
设置为位模式0xFFFFFFFC
,其被解释为无符号,为4294967292(2 32 - 4)。同样,b设置为2 32 - 5.当你添加两个时,得到0x1FFFFFFF7(8589934583),它比32位宽,所以额外的位被丢弃,留下4294967287,这个,碰巧的是,2 32 - 9.所以如果你对有符号的整数进行了这个计算,你就会得到完全相同的位模式,但是printf
会得到答案为-9
。
答案 3 :(得分:0)
使用谷歌,可以在两秒钟内找到答案..
http://en.wikipedia.org/wiki/Signedness
For example, 0xFFFFFFFF gives −1, but 0xFFFFFFFFU gives 4,294,967,295
for 32-bit code
因此,在这种情况下,您需要4294967287
。
但是,“从无符号到签名的投射不起作用是什么意思?”