首页 文章

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

提问于
浏览
1
#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 回答

  • 1

    我们是谁?”

    那里's no 2583629 , it'可能只是将有符号整数的位视为无符号的结果 . 通常two's complement将导致许多负值的值非常大 . 尝试以十六进制打印值以更清楚地查看模式,以十进制表示它们通常很难破译 .

  • 0

    我只是补充说,签名或未签名的概念是人类比机器更欣赏的东西 .

    假设一台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 的类型 .

  • 2

    将无效值分配给无符号变量的可能性并不常见 . 在这种情况下发生的隐式转换完全由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 显然是不同代码的结果,而不是您发布的代码 .

  • 2

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

    你得到的 Value 是由于二元补充 .

  • 0

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

    int i=-5;
    

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

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

相关问题