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