我们可以将带负数的整数分配给无符号整数吗?

时间:2013-12-12 15:21:21

标签: c

#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 个答案:

答案 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的原始值相匹配,这只是未定义行为的特定表现。

同时,第二个代码应该打印一个明确定义的正确值。它应该是模-5unsigned int转换为UINT_MAX + 1类型的结果。在你的情况下,模数可能恰好是2^32 = 4294967296,这就是你应该看到4294967296 - 5 = 4294967291的原因。

您如何设法获得4255644633并不清楚。您的4255644633显然是不同代码的结果,而不是您发布的代码。

答案 3 :(得分:0)

您可以根据编译器和设置获得警告(或可能失败)。

你得到的价值是由于二元补充。

答案 4 :(得分:0)

第二种情况下的输出不是垃圾值......

int i=-5;

当转换为二进制形式时,最高有效位被指定为'1',因为-5是负数..

但是当你使用%u时,二进制形式被视为正常数字,而MSB中的1被视为正常数字的一部分。