C++中的移位操作
Shift Operation in C++
为什么这段代码为 f1
和 f2
打印两个不同的数字?:
int main() {
int a = 32;
int f1 = (0xffffffff << a);
int f2 = (0xffffffff << 32);
std::cout << f1 << std::endl; // print -1
std::cout << f2 << std::endl; // print 0
}
对于 f2,我收到此警告,但对于 f1 则没有:
warning: left shift count >= width of type
我正在使用 g++ 4.4.7
结果
0xffffffff << 32
是
18446744069414584320
远大于 std::numeric_limits<int>::max()
如果你的系统将int
表示为4个字节,那么上面的值就是
2147483647
Signed overflow is undefined behavior 所以两者都表现出未定义的行为。
简短的回答是你是 invoking undefined behavior when shifting by width of type or greater。
更长的答案是,对于第二种情况,gcc 可以不断地折叠表达式并且只是移动到零 (see it live on godbolt):
movl [=10=], -28(%rbp) #, f2
而在第一种情况下它实际上执行了移位:
movl -20(%rbp), %eax # a, tmp63
movl $-1, %edx #, tmp64
movl %edx, %ebx # tmp64,
movl %eax, %ecx #,
sall %cl, %ebx #,
movl %ebx, %eax #, D.21248
movl %eax, -24(%rbp) # D.21248, f1
由于我们正在调用未定义的行为,因此我们对结果没有期望。对看似应该提供相同答案的不一致答案是完全可以接受的未定义行为。
为什么这段代码为 f1
和 f2
打印两个不同的数字?:
int main() {
int a = 32;
int f1 = (0xffffffff << a);
int f2 = (0xffffffff << 32);
std::cout << f1 << std::endl; // print -1
std::cout << f2 << std::endl; // print 0
}
对于 f2,我收到此警告,但对于 f1 则没有:
warning: left shift count >= width of type
我正在使用 g++ 4.4.7
结果
0xffffffff << 32
是
18446744069414584320
远大于 std::numeric_limits<int>::max()
如果你的系统将int
表示为4个字节,那么上面的值就是
2147483647
Signed overflow is undefined behavior 所以两者都表现出未定义的行为。
简短的回答是你是 invoking undefined behavior when shifting by width of type or greater。
更长的答案是,对于第二种情况,gcc 可以不断地折叠表达式并且只是移动到零 (see it live on godbolt):
movl [=10=], -28(%rbp) #, f2
而在第一种情况下它实际上执行了移位:
movl -20(%rbp), %eax # a, tmp63
movl $-1, %edx #, tmp64
movl %edx, %ebx # tmp64,
movl %eax, %ecx #,
sall %cl, %ebx #,
movl %ebx, %eax #, D.21248
movl %eax, -24(%rbp) # D.21248, f1
由于我们正在调用未定义的行为,因此我们对结果没有期望。对看似应该提供相同答案的不一致答案是完全可以接受的未定义行为。