C++ 为什么变量左移和常量左移产生不同的结果?

C++ 为什么变量左移和常量左移产生不同的结果?,c++,bit-shift,C++,Bit Shift,编译下面的代码后,我得到了一个奇怪的结果,a=1,b=0。有人能解释一下幕后发生了什么吗 #include<iostream> using namespace std; int main(){ int n=32; int a=1<<n; //turns out a=1 int b=1<<32; //turns out b=0 cout<<"a="<<a<<endl; cout&

编译下面的代码后,我得到了一个奇怪的结果,a=1,b=0。有人能解释一下幕后发生了什么吗

#include<iostream>
using namespace std;

int main(){

    int n=32; 
    int a=1<<n;  //turns out a=1
    int b=1<<32; //turns out b=0
    cout<<"a="<<a<<endl;
    cout<<"b="<<b<<endl;
}
#包括
使用名称空间std;
int main(){
int n=32;

int a=1因为您正在调用未定义的行为。移位的位数超过类型中存在的位数不被定义为具有任何特定行为

移位量过大:将uint32_t移位32位或更多位是错误的 未定义。我猜这是因为 不同CPU上的轮班操作对此执行不同的操作: 例如,X86将32位移位量截断为5位(因此,移位为 32位与移位0位相同),但PowerPC会截断 32位移位等于6位(因此32位移位产生零)。 由于这些硬件差异,行为完全不同 C未定义(因此在PowerPC上移位32位可能会格式化 硬盘,它不保证生产零)。的成本 要消除这种未定义的行为,编译器必须 为可变移位发出一个额外的操作(如“and”),该操作 这将使它们在普通CPU上的成本增加一倍


该标准没有定义,或者更确切地说,它将其定义为“未定义的行为”,即在左移位超出整数类型大小的情况下发生的情况。[这种未定义行为的原因是,不同硬件的行为可能相同,也可能不同,例如,向左移位32位]


在第一种情况下[至少没有优化],编译器生成指令来计算
1请在开发代码时始终启用并读取警告。例如,Gcc告诉您“左移位计数>=类型宽度”使用CLANG的<>代码-FSANITIZ=…./Cord>选项也是一个好主意。你正在张贴的代码显然是C++,但是你也用C标记。这两种语言倾向于在这样的边界情况下偏离,所以最好为你真正感兴趣的语言提问。一般来说,在签名类型上做移位操作不是一个好主意。