对于unsigned int的位移,为何为负?

时间:2014-12-23 08:25:32

标签: c++ c bit-shift unsigned

代码:

unsigned int i = 1<<31;
printf("%d\n", i);

为什么输出为-2147483648,为负值?


更新了问题:

#include <stdio.h>

int main(int argc, char * argv[]) {
    int i = 1<<31;
    unsigned int j = 1<<31;
    printf("%u, %u\n", i, j);
    printf("%d, %d\n", i, j);

    return 0;
}

上面的印刷品:

2147483648, 2147483648
-2147483648, -2147483648

那么,这是否意味着,签署了int&amp; unsigned int具有相同的位值,不同之处在于将第31位转换为数字值时如何处理?

6 个答案:

答案 0 :(得分:5)

%d打印int的{​​{1}}版本。对unsigned int i尝试%u

unsigned int

printf("%u\n", i);

int main(){ printf("%d, %u",-1,-1); return 0; }

即存储有符号整数的方式以及它如何从无符号转换为有符号整数或反之亦然将对您有所帮助。关注this

要回答您更新的问题,系统如何代表它们,即在2的补码中(如上述情况所示)     Output: -1, 4294967295

答案 1 :(得分:4)

%u

使用“unsigned int
 printf("%u\n", i);

............................................... ........

对更新问题的响应:任何位序列都可以解释为有符号或无符号值。

答案 2 :(得分:3)

printf("%d\n", i);调用UBiunsigned int,您尝试将其打印为signed int。写1 << 31而不是1U << 31也是未定义的。

将其打印为:

printf("%u\n", i);

printf("%X\n", i);

关于您更新的问题,它也会出于同样的原因调用UB(如果您使用'1U'而不是1,那么因为int初始化为1U << 31超出范围值。如果unsigned初始化超出范围值,则模块化算法进入图像并且分配余数。对于signed,行为未定义。)

了解平台上的行为
在您的平台上,int似乎是4个字节。当您编写1 << 31之类的内容时,它会转换为您计算机上的位图0x80000000

现在,当您尝试将此模式打印为已签名时,它会在2s完成系统中打印带符号的解释,即-2 31 (AKA INT_MIN)。当您将其打印为无符号时,您会得到2 31 作为输出。


<强>学习收获
1.使用1U << 31代替1 << 31
2.始终在printf中使用正确的打印说明符 3.将正确的参数类型传递给variadic functions 4.当隐式类型转换(无符号 - >带符号,宽类型 - >窄类型)发生时要小心。如果可能的话,完全避免这种铸件。

答案 3 :(得分:3)

尝试

printf("%u\n", i);

通过使用%d说明符,printf期望参数为int,并将其转换为int。 因此,请%u使用unsigned int

答案 4 :(得分:3)

您没有在unsigned上进行轮班操作,而是在signed int上进行轮班操作。

  • 1signed
  • 然后换档操作转移到符号位 signed(假设int是32位宽),这已经是未定义的行为
  • 然后将编译器认为他想要的任何内容分配给unsigned
  • 然后您打印unsigned作为签名,再次没有定义的行为。

答案 5 :(得分:2)

%u用于unsigned int %d用于签名int。

程序输出中的

2147483648, 2147483648     (output for unsigned int)
-2147483648, -2147483648   (output for signed int )