为什么GCC中long long执行1<<48会触发溢出警告
问题原因
你遇到的异常现象核心是C语言整数常量的默认类型规则与左移运算的类型推导逻辑导致的,具体如下:
- 不带后缀的十进制整数常量
1,默认类型是int。哪怕是在64位编译环境中,绝大多数编译器的int类型长度仍然是4字节(32位),而非你预期的8字节64位。 - 左移运算符
<<的结果类型与左操作数的类型完全一致。你执行1 << 48时,左操作数是32位的int,移动位数48远大于32位的类型宽度,属于C标准规定的未定义行为,因此编译器会抛出溢出警告;实际运算时高位全部被截断,得到的结果是0,后续赋值给unsigned long long类型的two48也不会修正这个错误结果。 - 你通过
two16 * two16 * two16得到正确结果,是因为two16本身就是unsigned long long类型,乘法运算全程在64位无符号整数规则下执行,不存在溢出截断问题。
修复方案
如果要执行64位宽度的左移操作,需要给整数常量加上ULL后缀,明确指定它是无符号长长整数类型:
two48 = 1ULL << 48;
修改后即可得到正确的2^48计算结果。
内容的提问来源于stack exchange,提问作者Greg
相关产品推荐
相关产品推荐

