c/c ++左移无符号与有符号 [英] c/c++ left shift unsigned vs signed

查看:187
本文介绍了c/c ++左移无符号与有符号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个代码.

#include <iostream>

int main()
{
    unsigned long int i = 1U << 31;
    std::cout << i << std::endl;
    unsigned long int uwantsum = 1 << 31;
    std::cout << uwantsum << std::endl;
    return 0;
}

它打印出来.

2147483648
18446744071562067968

在Arch Linux 64位,gcc,常春藤桥体系结构上.

on Arch Linux 64 bit, gcc, ivy bridge architecture.

第一个结果很有意义,但是我不知道第二个数字是从哪里来的. 1个表示为4字节整数的有符号或无符号的

The first result makes sense, but I don't understand where the second number came from. 1 represented as a 4byte int signed or unsigned is

00000000000000000000000000000001

当您将其向左移动31次时,您最终会得到

When you shift it 31 times to the left, you end up with

10000000000000000000000000000000

不?我知道正数向左移动本质上是2 ^ k,其中k是您将其移动多少次,前提是它仍然适合边界.为什么我会得到这么奇怪的数字?

no? I know shifting left for positive numbers is essentially 2^k where k is how many times you shift it, assuming it still fits within bounds. Why is it I get such a bizarre number?

推荐答案

大概您对为什么这样感兴趣:unsigned long int uwantsum = 1 << 31;产生一个奇怪的"值.

Presumably you're interested in why this: unsigned long int uwantsum = 1 << 31; produces a "strange" value.

问题非常简单:1是普通的int,因此在普通的int上进行移位,并且只有在完成后才将结果转换为unsigned long.

The problem is pretty simple: 1 is a plain int, so the shift is done on a plain int, and only after it's complete is the result converted to unsigned long.

但是,在这种情况下,1<<31溢出了32位有符号整数的范围,因此结果是不确定的 1 .转换为无符号后,结果仍然不确定.

In this case, however, 1<<31 overflows the range of a 32-bit signed int, so the result is undefined1. After conversion to unsigned, the result remains undefined.

也就是说,在大多数典型情况下,1<<31可能会给出10000000000000000000000000000000的位模式.当被视为带符号的2的补码 2 编号时,它是-2147483648.由于这是负面的,因此当将其转换为64位类型时,将对其进行符号扩展,因此前32位将填充第31位的副本.这给出:1111111111111111111111111111111110000000000000000000000000000000(33个1位,后跟31个0位.)

That said, in most typical cases, what's likely to happen is that 1<<31 will give a bit pattern of 10000000000000000000000000000000. When viewed as a signed 2's complement2 number, this is -2147483648. Since that's negative, when it's converted to a 64-bit type, it'll be sign extended, so the top 32 bits will be filled with copies of what's in bit 31. That gives: 1111111111111111111111111111111110000000000000000000000000000000 (33 1-bits followed by 31 0-bits).

如果然后将其视为无符号64位数字,则会得到18446744071562067968.

If we then treat that as an unsigned 64-bit number, we get 18446744071562067968.

  1. 第5.8/2节:
  1. §5.8/2:

E1的值<< E2是E1左移E2位的位置;空出的位为零.如果E1具有无符号类型,则结果的值为E1×2E2,与结果类型中可表示的最大值相比,以模为底减少了1.否则,如果E1有符号类型且非负值,并且E1×2E2在结果类型的相应无符号类型中可表示,则该值(转换为结果类型)为结果值;否则,结果为0. 否则,行为是不确定的.

The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are zero-filled. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. Otherwise, if E1 has a signed type and non-negative value, and E1×2E2 is representable in the corresponding unsigned type of the result type, then that value, converted to the result type, is the resulting value; otherwise, the behavior is undefined.

  • 理论上,计算机可以使用1的补码或带符号的幅度来表示带符号的数字-但是2的补码目前比这两个都更普遍.如果它确实使用了其中之一,那么我们期望最终结果会有所不同.
  • 这篇关于c/c ++左移无符号与有符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆