#include<stdio.h>
#include<conio.h>
main()
{
int i=-5;
unsigned int j=i;
printf("%d",j);
getch();
}
O/p
-----
-5
#include<stdio.h>
#include<conio.h>
main()
{
int i=-5;
unsigned int j=i;
printf("%u",j);
getch();
}
O/p
===
4255644633
这里我没有收到任何编译错误。
使用标识符%d打印时给出-5,使用%u打印时打印一些垃圾值。
我想知道的事情是
1)为什么编译器在将带负数的整数赋值给unsigned int时忽略。
2)如何将签名转换为无符号?
答案 0 :(得分:2)
谁是“我们?”
没有“垃圾值”,它可能只是将有符号整数的位视为无符号的结果。通常two's complement会导致许多负值的值非常大。尝试以十六进制打印值以更清晰地查看模式,以十进制表示它们通常难以解密。
答案 1 :(得分:2)
我只想补充一点,签名或未签名的概念是人类比机器更欣赏的东西。
假设一台32位机器,你的-5值将由32位值0xFFFFFFFB(二进制补码)在内部表示。
当您在源代码中插入printf("%d",j);
时,编译器可能不关心j是有符号还是无符号,它只是将0xFFFFFFFB推送到堆栈上,然后是指向"%d"
字符串的指针。调用时printf
函数查看格式字符串,看到%d
,并从中知道它必须解释 0xFFFFFFFB为签名值,因此它显示-5
,尽管j
是无符号整数。
另一方面,当您编写printf("%u",j);
时,"%u"
会使printf
将您的0xFFFFFFF解释为无符号值。该值为2 ^ 32 - 5,或4294967291。
传递给printf
的格式字符串决定了如何解释值,而不是变量j
的类型。
答案 2 :(得分:1)
将无效值赋给无符号变量的可能性并不常见。在这种情况下发生的隐式转换完全由C语言定义。根据模运算的规则将该值引入目标无符号类型的范围。模数等于2^N
,其中N
是无符号收件人中的值位数。这就是C一直以来的情况。
使用unsigned int
说明符打印%d
值是没有意义的。此说明符需要signed int
参数。由于这种不匹配,您的第一个代码的行为是未定义的。
换句话说,关于哪个值是垃圾而哪个不是垃圾,你完全倒退了。
由于未定义的行为,您的第一个代码实际上是“打印垃圾值”。事实上,它碰巧与-5
的原始值相匹配,这只是未定义行为的特定表现。
同时,第二个代码应该打印一个明确定义的正确值。它应该是模-5
将unsigned int
转换为UINT_MAX + 1
类型的结果。在你的情况下,模数可能恰好是2^32 = 4294967296
,这就是你应该看到4294967296 - 5 = 4294967291
的原因。
您如何设法获得4255644633
并不清楚。您的4255644633
显然是不同代码的结果,而不是您发布的代码。
答案 3 :(得分:0)
您可以根据编译器和设置获得警告(或可能失败)。
你得到的价值是由于二元补充。
答案 4 :(得分:0)
第二种情况下的输出不是垃圾值......
int i=-5;
当转换为二进制形式时,最高有效位被指定为'1',因为-5是负数..
但是当你使用%u时,二进制形式被视为正常数字,而MSB中的1被视为正常数字的一部分。