将2^31赋给有符号和无符号的32位整数变量后的奇怪结果
Weird result after assigning 2^31 to a signed and unsigned 32-bit integer variable
正如问题标题所示,将2^31赋给有符号和无符号的32位整数变量会产生意外结果。
这是一个短程序(在C++
中),我制作它是为了看看发生了什么:
#include <cstdio>
using namespace std;
int main()
{
unsigned long long n = 1<<31;
long long n2 = 1<<31; // this works as expected
printf("%llun",n);
printf("%lldn",n2);
printf("size of ULL: %d, size of LL: %dn", 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()
:
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("%llun",n);
}
在编译和运行时,这让我更加困惑:
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是该数据类型的最大值吗?
我突然想到,也许n*2和n<lt;1,不要总是以同样的方式行事,所以我尝试了这个:
void s()
{
unsigned long long n = 1;
for(int a=0;a<63;a++) n = n*2;
printf("%llun",n);
}
这给出了2^63的正确值作为9223372036854775808
的输出(我使用python验证了它)。但是做左大便有什么错?
左算术移位n等于乘以2n(如果值不溢出)
-维基百科
该值没有溢出,由于该值为2^63(所有位都已设置),因此只会出现减号。
我仍然无法弄清楚左班是怎么回事,有人能解释一下吗?
PS:这个程序是在运行linux mint的32位系统上运行的(如果有帮助的话)
在这一行:
unsigned long long n = 1<<32;
问题是文字1
的类型是int
,可能只有32位。因此,移位会将其推到界外。
存储到较大的数据类型并不意味着表达式中的所有内容都是以较大的大小完成的。
因此,要更正它,您需要将其转换为unsigned long long
文字:
unsigned long long n = (unsigned long long)1 << 32;
unsigned long long n = 1ULL << 32;
1 << 32
失败的原因是1
没有正确的类型(它是int
)。编译器在赋值本身实际发生之前不会进行任何转换,因此1 << 32
使用int
算法进行计算,并发出溢出警告。
请尝试使用1LL
或1ULL
,它们分别具有long long
和unsigned long long
类型。
行
unsigned long long n = 1<<32;
导致溢出,因为文字1的类型是int
,所以1 << 32
也是int,在大多数情况下是32位。
线路
unsigned long long n = 1<<31;
由于同样的原因,也会溢出。请注意,1的类型是signed int
,因此它实际上只有31位的值和1位的符号。因此,当您对1 << 31
进行移位时,它会溢出值位,从而产生-2147483648
,然后将其转换为无符号长整型,即18446744071562067968
。如果检查变量并进行转换,则可以在调试器中对此进行验证。
所以使用
unsigned long long n = 1ULL << 31;
- 如何忽略32位整数中的特定位
- 检测 32 位整数溢出
- 将 64 位整数中的每个其他位与 32 位整数进行比较
- 对 32 位整数进行哈希处理比对 3 个 16 位整数的哈希进行按位运算慢?
- 将 32 位大端有符号整数转换为有符号小端整数
- 如何将 32 位无符号整数分配给包含 32 位的位字段
- SSE 整数 2^n 的 2 次方,对于没有 AVX2 的 32 位整数
- 32 位整数缩放,无溢出
- 获取两个无符号整数 C++ 乘积的高 32 位的有效方法
- Visual C 32位整数从文件到8位字符到文件 - 程序在某些整数上崩溃
- 有没有办法让32位C 编译器遵循16位整数促销规则
- C++:如何将 32 位数据转换为有符号整数
- 我们是否需要担心 32 位或 64 位整数,或者我们只使用 'int'
- 将 32 位浮点数和不强制转换的 32 位整数与双精度进行比较,当其中一个值可能太大而无法完全适合另一种类型时
- 优化 32 位架构上的可移植 128 位整数移位
- 尝试从另一个过程读取32位整数时,ReadProcessMemory崩溃了
- 如何在AVX2中从32位转换为16位未签名的整数
- AVX __M256I整数部门用于签名的32位元素
- 将浮点数 32 位变量类型转换为无符号整数 32 位时进行了哪些位级更改
- 左移一个整数32位