将2 ^ 31分配给有符号和无符号32位整数变量后的结果很奇怪 [英] Weird result after assigning 2^31 to a signed and unsigned 32-bit integer variable
问题描述
问题标题显示,将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屋!