C中的无符号值
我有以下代码:
#include 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
单词是什么?
将int -1
分配给unsigned
:由于-1
不适合[0...UINT_MAX]
范围,因此添加UINT_MAX+1
倍数,直到答案在范围内。 显然UINT_MAX
是OP的机器上的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
as unsigned
的值为4294967295.作为int
,取决于有符号整数编码,它的值为-1,-2147483647或TBD。 作为float
它可能是NAN 。
什么是无符号的单词?
unsigned
存储[0 ... UINT_MAX]
范围内的[0 ... UINT_MAX]
。 它永远不会有负值。 如果代码需要非负数,请使用unsigned
。 如果代码需要可能是+, – 或0的计数,请使用int
。
更新:为避免编译器警告将signed int
分配给unsigned
,请使用以下命令。 这是一个无效的unsigned
1u
– 如上所述。 效果与-1
相同,但传达给编译器直接意图。
unsigned int a = -1u;
在变量声明中使用unsigned
对程序员本身更有用 – 不要将变量视为负数。 正如您所注意到的, -1
和4294967295
对于4字节整数具有完全相同的位表示。 这都是关于你想如何对待或看到它们的。
语句unsigned int a = -1;
在二进制补码中转换-1
并在a
分配位表示。 printf()
说明符x
, d
和u
表示存储在变量a
的位表示如何以不同的格式显示。
将unsigned int a to -1;
初始化unsigned int a to -1;
这意味着你将2's
补码-1
存储到a
的内存中。
这只不过是0xffffffff
或4294967295
。
因此,当您使用%x or %u
格式说明符打印它时,您将获得该输出。
通过指定变量的签名来确定可以存储的值的最小和最大限制。
与unsigned int
一样:范围从0 to 4,294,967,295
和int
:范围从-2,147,483,648 to 2,147,483,647
有关签名的更多信息,请参阅此处
在hex中,它不能得到负值。 所以它表现得像ffffffff 。
使用无符号版本的优势(当您知道所包含的值将是非负的)时,有时计算机将为您发现错误(当向变量赋值为负值时,程序将“ 崩溃 ”)。