将2 ^ 31分配给有符号和无符号32位整数变量后的结果很奇怪 [英] Weird result after assigning 2^31 to a signed and unsigned 32-bit integer variable

查看:314
本文介绍了将2 ^ 31分配给有符号和无符号32位整数变量后的结果很奇怪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题标题显示,将2 ^ 31分配给有符号和无符号的32位整数变量会产生意外的结果.

As the question title reads, assigning 2^31 to a signed and unsigned 32-bit integer variable gives an unexpected result.

这是简短的程序(在C++中),我制作了该程序以查看发生了什么事情:

Here is the short program (in C++), which I made to see what's going on:

#include <cstdio>
using namespace std;

int main()
{
    unsigned long long n = 1<<31;
    long long n2 = 1<<31;  // this works as expected
    printf("%llu\n",n);
    printf("%lld\n",n2);
    printf("size of ULL: %d, size of LL: %d\n", sizeof(unsigned long long), sizeof(long long) );
    return 0;
}

这是输出:

MyPC / # c++ test.cpp -o test
MyPC / # ./test
18446744071562067968      <- Should be 2^31 right?
-2147483648               <- This is correct ( -2^31 because of the sign bit)
size of ULL: 8, size of LL: 8

然后我向其中添加了另一个功能p():

I then added another function p(), to it:

void p()
{
  unsigned long long n = 1<<32;  // since n is 8 bytes, this should be legal for any integer from 32 to 63
  printf("%llu\n",n);
}

在编译和运行时,这让我更加困惑:

On compiling and running, this is what confused me even more:

MyPC / # c++ test.cpp -o test
test.cpp: In function ‘void p()’:
test.cpp:6:28: warning: left shift count >= width of type [enabled by default]
MyPC / # ./test 
0
MyPC /

为什么编译器会抱怨左移计数太大? sizeof(unsigned long long)返回8,这不是说2 ^ 63-1是该数据类型的最大值吗?

Why should the compiler complain about left shift count being too large? sizeof(unsigned long long) returns 8, so doesn't that mean 2^63-1 is the max value for that data type?

让我吃惊的是,也许n * 2和n << 1并不总是以相同的方式表现,所以我尝试了这一点:

It struck me that maybe n*2 and n<<1, don't always behave in the same manner, so I tried this:

void s()
{
   unsigned long long n = 1;
   for(int a=0;a<63;a++) n = n*2;
   printf("%llu\n",n);
}

这给出了正确的值2 ^ 63作为9223372036854775808的输出(我使用python进行了验证).但是做左屎怎么了?

This gives the correct value of 2^63 as the output which is 9223372036854775808 (I verified it using python). But what is wrong with doing a left shit?

左算术移位n等于乘以2 n (前提是该值不会溢出)

A left arithmetic shift by n is equivalent to multiplying by 2n (provided the value does not overflow)

-Wikipedia

该值没有溢出,因为该值为2 ^ 63(所有位均已设置),所以只会出现一个负号.

The value is not overflowing, only a minus sign will appear since the value is 2^63 (all bits are set).

我仍然无法弄清楚左移是怎么回事,任何人都可以解释一下吗?

I'm still unable to figure out what's going on with left shift, can anyone please explain this?

PS:该程序在运行linux mint的32位系统上运行(如果有帮助的话)

PS: This program was run on a 32-bit system running linux mint (if that helps)

推荐答案

在此行:

unsigned long long n = 1<<32;

问题在于文字1的类型为int-可能只有32位.因此,这种转变将使它超出范围.

The problem is that the literal 1 is of type int - which is probably only 32 bits. Therefore the shift will push it out of bounds.

仅仅因为您要存储到更大的数据类型中,并不意味着表达式中的所有内容都以该更大的大小完成.

Just because you're storing into a larger datatype doesn't mean that everything in the expression is done at that larger size.

因此,要更正它,您需要将其强制转换或将其设置为unsigned long long文字:

So to correct it, you need to either cast it up or make it an unsigned long long literal:

unsigned long long n = (unsigned long long)1 << 32;
unsigned long long n = 1ULL << 32;

这篇关于将2 ^ 31分配给有符号和无符号32位整数变量后的结果很奇怪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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