左移在GCC中严重出错

Left shift goes heavily wrong with GCC

本文关键字:出错 GCC 左移      更新时间:2023-10-16

我已经看了这段代码一个小时了......我拼命地试图找到错误。

#include <iostream>
int main()
{
    for (int32_t n = 1; n>= 0; n--)
    {
        std::cout << "n: " << n << std::endl;
        std::cout << std::dec << "  64 - n: " << (64 - n) << std::endl;
        std::cout << std::hex << "  0x1ULL << 64: " << (0x1ULL << 64) << std::endl;
        std::cout << std::hex << "  0x1ULL << (64 - n): " << (0x1ULL << (64 - n)) << std::endl;
    }
}

这就是输出:

n: 1
  64 - n: 63
  0x1ULL << 64: 0
  0x1ULL << (64 - n): 8000000000000000
n: 0
  64 - n: 64
  0x1ULL << 64: 0
  0x1ULL << (64 - n): 1

为什么 n = 0 时 (0x1ULL <<64) 与 (0x1ULL <<(64 - n)) 不同?n 的类型似乎无关紧要。

每个版本的 GCC 都是一样的。随意在线试用:http://www.compileonline.com/compile_cpp11_online.php

您有未定义的行为:

C++11 5.8/1 如果操作数正确,则行为未定义 为负数,或大于或等于提升的左操作数的长度(以位为单位)。

因此,假设long long有 64 位,移位 64 位将产生未定义的行为。

左移计数应小于字体宽度。在本例中,int32_t 类型的宽度为 32 位,并且您正在移动超过其容量。这是不对的。