任何人都可以帮助我理解以下行为。
1 #include <iostream>
2
3 using namespace std;
4
5 main()
6 {
7 uint32_t i = 32;
8
9 // cout << "(1<<32): " << (1<<32) << endl; // - This leads to a compilation error.
10 cout << "(1<<32): " << (1<<i) << endl; // - This compiles and prints 1 - Why?
11
12 return 0;
13 }
如果我取消注释上面的第9行 - 我看到以下编译错误(这对我来说很有意义)
BitWiseLeftShift.c++: In function 'int main()':
BitWiseLeftShift.c++:9: warning: left shift count >= width of type
但第10行是我的问题所在。它成功编译并打印
(1<<32): 1
像圆形位移一样。为什么要打印1?
我已经看到i == 33
,(1<<i)
打印2。
我确实搜索了论坛,找不到相关问题。如果这是一个重复的问题 - 请帮我一个链接。
答案 0 :(得分:7)
转换不合法,但编译器只捕获第一个:
6.5.7
对每个操作数执行整数提升。类型 结果是提升左操作数的结果。如果值 右操作数为负或大于或等于宽度 提升的左操作数,行为未定义。
答案 1 :(得分:5)
正如其他答案中所指出的,如果移位量大于或等于位移位数据的大小(或为负数),则结果是未定义的。
然而,要解释你所看到的行为 -
某些计算机体系结构(包括x86)将移位量视为模数被移位的数据的模数,因此移位32相当于根本不移位。换句话说,它们只是掩盖了较高的位并使用较低的位。
答案 2 :(得分:4)
首先,这不是错误,这是一个警告。编译器在第二种情况下没有发出警告的原因是它可能不够聪明,无法从第一个赋值中推断出结果将是未定义的行为,而在第一种情况下,常数左移32位是“显然”是编译器捕获的问题。
答案 3 :(得分:1)
在常量折叠期间,由预处理器评估常量移位,而第二个由大多数编译器推迟到运行时。这将解释编译器连续传递的不同响应。
静态分析可以确定两者确实具有相同的结果,并且可以在编译期间检测到。