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对程序员本身更有用 – 不要将变量视为负数。 正如您所注意到的, -14294967295对于4字节整数具有完全相同的位表示。 这都是关于你想如何对待看到它们的。

语句unsigned int a = -1; 在二进制补码中转换-1并在a分配位表示。 printf()说明符xdu表示存储在变量a的位表示如何以不同的格式显示。

unsigned int a to -1;初始化unsigned int a to -1; 这意味着你将2's补码-1存储到a的内存中。
这只不过是0xffffffff4294967295

因此,当您使用%x or %u格式说明符打印它时,您将获得该输出。

通过指定变量的签名来确定可以存储的值的最小和最大限制。

unsigned int一样:范围从0 to 4,294,967,295int :范围从-2,147,483,648 to 2,147,483,647

有关签名的更多信息,请参阅此处

hex中,它不能得到负值。 所以它表现得像ffffffff

使用无符号版本的优势(当您知道所包含的值将是非负的)时,有时计算机将为您发现错误(当向变量赋值为负值时,程序将“ 崩溃 ”)。