2013-09-30 117 views
1

(unsigned)~0(unsigned)1有什么区别?为什么unsigned~0-1unsigned11?它是否与无符号数字存储在内存中的方式有​​关。为什么一个无符号数给出了一个签名结果。它也没有给出任何溢出错误。我使用GCC编译:'(无符号)1'和'(无符号)〜0'之间的区别

#include<sdio.h> 
main() 
{ 
unsigned int x=(unsigned)~0; 
unsigned int y=(unsigned)1; 
printf("%d\n",x); //prints -1 
printf("%d\n",y); //prints 1 
} 
+0

不是'〜0'的行为是依赖于实现的读取:[在C中计算数据类型的范围](http://stackoverflow.com/questions/17796041/calculating-ranges-of-data-types-in-c/17796122#17796122) –

回答

5

因为%d是一个符号整数说明符。使用%u。我的机器上打印4294967295

正如其他人所提到的,如果您将最高的无符号值解释为有符号值,您将得到-1,请参阅维基百科条目two's complement

+0

哦谢谢!为什么它不是1而是4294967295 – programer8

+0

,因为运算符会反转*所有位。 –

+0

'〜'是一个按位不操作符,并翻转所有位。也许你正在想'''(逻辑不是),这可能会给你1。 – Dmitri

1

您的系统使用负数表示two's complement。在这种表示中,由所有1组成的二进制数表示最大的负数-1

由于反转零的所有位为您提供了所有的人组成的号码,你会得到-1当你通过与%d一个希望将签署号印字它重新诠释作为有符号数数,不是未签名的。

+0

哦谢谢解释。 – programer8

0

printf()只知道通过格式字符串中使用的格式说明符传递的变量类型。所以这里发生的是你正在打印xy作为签署整数,因为你在你的格式字符串中使用了%d。改为尝试%u,你会得到一个更符合你可能期望的结果。

1

首先,在使用printf时,您要求它将数字打印为有符号(“%d”)而不是无符号(“%u”)。

其次,你是对的,它有“与数字存储在内存中的方式有​​关”。 int(有符号或无符号)不是计算机上的单个位,而是k位的集合。 k的确切值取决于计算机体系结构的具体情况,但最有可能的是k = 32。为了简洁起见,假定你的整数是8位长,所以k = 8(这当然不是这种情况,除非你在一个非常有限的嵌入式系统上工作)。在这种情况下,(int)0实际上是00000000,并且(int)〜0(它抵消所有位)是11111111.

最后,在二进制补码(这是最常见的有符号数的二进制表示)中,11111111实际上是-1。请参阅http://en.wikipedia.org/wiki/Two的补充说明二进制补码。

如果你改变你的打印使用“%u”,那么它将打印一个正整数,表示(2^k-1)其中k是整数中的位数(所以可能会打印4294967295) 。

相关问题