我有以下代码:
#include <stdio.h>
int main() {
unsigned int a = -1;
int b = -1;
printf("%x\n", a);
printf("%x\n", b);
printf("%d\n", a);
printf("%d\n", b);
printf("%u\n", a);
printf("%u\n", b);
return 0;
}
输出结果为:
ffffffff
ffffffff
-1
-1
4294967295
4294967295
我可以看到根据传递给printf
函数的值将值解释为有符号或无符号。在这两种情况下,字节都是相同的(ffffffff
)。然后,unsigned
单词是什么?
答案 0 :(得分:12)
将int -1
分配给unsigned
:由于-1
不适合[0...UINT_MAX]
范围,所以会添加UINT_MAX+1
的倍数,直到答案为止范围。在OP的计算机上显然UINT_MAX
为pow(2,32)-1 or 429496725
,因此 a
的值为 4294967295 。
unsigned int a = -1;
"%x"
,"%u"
说明符需要匹配unsigned
。由于这些不匹配,“如果转换规范无效,则行为未定义。
如果任何参数不是相应转换规范的正确类型,则行为未定义。“C11§7.21.6.19。printf说明符不会更改b
。
printf("%x\n", b); // UB
printf("%u\n", b); // UB
"%d"
说明符需要匹配int
。由于这些不匹配,因此更多 UB 。
printf("%d\n", a); // UB
鉴于未定义的行为,不支持结论。
两种情况下,字节都相同(ffffffff)。
即使使用相同的位模式,不同的类型也可能具有不同的值。 ffffffff
unsigned
的值为4294967295.作为int
,取决于有符号整数编码,其值为-1,-2147483647或TBD。作为float
,它可能是NAN。
什么是无符号字?
unsigned
存储[0 ... UINT_MAX]
范围内的整数。它永远不会有负值。如果代码需要非负数,请使用unsigned
。如果代码需要可能是+, - 或0的计数,请使用int
。
更新:为避免编译器发出有关将签名int
分配给unsigned
的警告,请使用以下内容。这是unsigned
1u
被否定的 - 如上所述。效果与-1
相同,但传达给编译器直接意图。
unsigned int a = -1u;
答案 1 :(得分:0)
在变量声明中使用unsigned
对程序员本身更有用 - 不要将变量视为负数。正如您所注意到的,-1
和4294967295
对于4字节整数具有完全相同的位表示。这完全取决于您希望如何对待或查看。
语句unsigned int a = -1;
正在将-1
转换为二进制补码,并在a
中分配位表示。 printf()
说明符x
,d
和u
显示了变量a
中存储的位表示形式如何以不同的格式显示。
答案 2 :(得分:0)
初始化unsigned int a to -1;
时,表示您将 2's
的 -1
补充存储到{{{}}的内存中1}}。
这只不过是a
或0xffffffff
。
因此,当您使用4294967295
格式说明符打印它时,您将获得该输出。
通过指定变量的签名来决定可以存储的值的最小和最大限制。
与%x or %u
一样:范围来自unsigned int
和0 to 4,294,967,295
:范围来自int
有关签名的更多信息,请参阅this
答案 3 :(得分:-5)
在十六进制中,它无法获得负值。因此它显示为 ffffffff 。
使用未签名版本的优势(当您知道所包含的值将是非负的)时,有时计算机会为您发现错误(程序将&#34; 崩溃 &#34;当负值分配给变量时)。