C中的无符号值
我有以下代码:C中的无符号值,c,printf,unsigned,C,Printf,Unsigned,我有以下代码: #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; } 我可以看到
#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;
}
我可以看到,根据传递给printf
函数的值,值被解释为有符号或无符号。在这两种情况下,字节是相同的(ffffffff
)。那么,无符号的
字是什么意思?在十六进制中,它不能得到负值。所以它显示为ffffffff
unsigned int a = -1;
printf("%d\n", a); // UB
使用无符号版本(当您知道包含的值为非负值时)的优点是,有时计算机会为您发现错误(当负值分配给变量时,程序将“崩溃)。正如您所注意到的,对于4字节整数,
-1
和4294967295
具有完全相同的位表示。这一切都是关于你想如何对待他们,或是看他们
语句
无符号int a=-1
正在将-1
转换为2的补码,并在a
中分配位表示。printf()
表示您正在将-1
的补码存储到a的内存中
它只不过是0xffffffff
或4294967295
因此,当您使用%x或%u
格式说明符打印它时,您将获得该输出
通过指定变量的有符号性来决定可存储值的最小和最大限制
与unsigned int
类似:范围从0到4294967295
和int
:范围从-2147483648到2147483647
有关签名的更多信息,请参考将int-1
分配给未签名的:由于-1
不适合范围[0…UINT\u MAX]
,因此会添加UINT\u MAX+1的倍数,直到答案在范围内。显然,UINT_MAX
在OP的机器上是pow(2,32)-1或429496725
,因此a
的值为4294967295
unsigned int a = -1;
printf("%d\n", a); // UB
“%x”
,“%u”
说明符需要一个匹配的无符号的。由于这些不匹配,“如果转换规范无效,则行为未定义。
如果任何参数不是相应转换规范的正确类型,行为未定义“C11§7.21.6.1 9。printf说明符不会更改b
printf("%x\n", b); // UB
printf("%u\n", b); // UB
“%d”
说明符需要匹配的int
。因为这些不匹配,所以更多的UB
unsigned int a = -1;
printf("%d\n", a); // UB
鉴于未定义的行为,这些结论不受支持
在这两种情况下,字节都是相同的(ffffffff)
即使使用相同的位模式,不同的类型也可能有不同的值ffffff
作为一个无符号的
的值为4294967295。作为一个int
,根据有符号整数编码,它的值为-1、-2147483647或TBD。作为一个浮点
它可能是一个
无符号字是什么意思
unsigned
存储范围为[0…UINT\u MAX]
的整数。它从来没有负值。如果代码需要非负数,请使用无符号
。如果代码需要一个计数数,可以是+、-或0,请使用int
更新:要避免编译器警告将有符号的int
分配给无符号的,请使用以下命令。这是一个被求反的无符号1u
,其定义如上所述。其效果与-1
相同,但向编译器传达了直接意图
unsigned int a = -1u;
请参阅:简短的回答是“如果最高有效位为1
,则将其解释为负整数”。@rvillablanca“如果我可以看到有符号变量打印为有符号或无符号”-您不能,使用%d
打印无符号值和使用%u
或%x
打印有符号值是未定义的行为。您的一些printf语句是UB,它主导了这个问题。这是未定义的行为。没有人能理解“打印ffffffff可以打印为有符号-1或无符号4294967295”的意思。如果先将值强制转换为正确的类型,则相同的位模式在printf中可以使用相应的格式被视为有符号或无符号。为无符号
变量指定负值的可能重复行为有明确定义。无符号i=-1代码>始终将INT_MAX值指定给i。你关于UB的陈述是不正确的。请重新阅读你引用的段落。TL;DR:遵循语法的任何转换说明符都是“有效的”。换句话说,在printf(“%d”,“foo”)
中,说明符“%d”在引用段落所指的意义上是有效的。当然,尝试将字符串打印为int是不正确的,但这并不是因为您认为的原因。相反,“如果允许,将执行适当的类型升级或转换”,并且由于不允许从字符串到int的类型升级或转换,因此将变为UB。@AnorZaken Answer进行了修改,以强调printf说明符和参数类型不匹配。Err,为什么没有为无符号整数b
?@Columbo和int b=-1定义说明符%u
,b
不是无符号整数,而是值为-1的int
。使用不匹配的说明符打印是UB-正数有一个例外,但这不适用于这里。贝卡,这太不可读了