按位的意外行为使用gcc移 [英] unexpected behavior of bitwise shifting using gcc
问题描述
我有一个测试的程序是这样的:
I have a test program like this:
int main()
{
unsigned n = 32;
printf("ans << 32 = 0x%X\n", (~0x0U) << 32);
printf("ans >> 32 = 0x%X\n", (~0x0U) >> 32);
printf("ans << n(32) = 0x%X\n", (~0x0U) << n);
printf("ans >> n(32) = 0x%X\n", (~0x0U) >> n);
return 0;
}
它产生的输出如下:
It produces the following output:
ans << 32 = 0x0 ... (1)
ans >> 32 = 0x0 ... (2)
ans << n(32) = 0xFFFFFFFF ... (3)
ans >> n(32) = 0xFFFFFFFF ... (4)
我期待(1)和(3)是相同的,以及(2)和(4)是相同的。
I was expecting (1) and (3) to be the same, as well as (2) and (4) to be the same.
使用gcc版本:gcc.real(Ubuntu的4.4.1-4ubuntu9)4.4.1
Using gcc version: gcc.real (Ubuntu 4.4.1-4ubuntu9) 4.4.1
这是怎么回事?
推荐答案
由类型的大小为转移不确定的行为,根据的 C标准,第6.5.7.3:
Shifting by the size of the type is undefined behavior, according to the C standard, § 6.5.7.3:
6.5.7按位移位运算符
(...)如果值
右操作数为负或大于或等于更大的宽度
推广左操作数,行为是理解过程网络定义。
6.5.7 Bitwise shift operators
(...) If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
您编译器应该提醒你一下:
Your compiler should warn you about this:
$ gcc shift.c -o shift -Wall
shift.c: In function ‘main’:
shift.c:5:5: warning: left shift count >= width of type [enabled by default]
shift.c:6:5: warning: right shift count >= width of type [enabled by default]
如果你看一下汇编code 的gcc产生,你会看到它实际上是计算前两个结果在编译的时候。简化的:
If you look at the assembler code gcc is generating, you'll see it is actually calculating the first two results at compilation time. Simplified:
main:
movl $0, %esi
call printf
movl $0, %esi
call printf
movl -4(%rbp), %ecx ; -4(%rbp) is n
movl $-1, %esi
sall %cl, %esi ; This ignores all but the 5 lowest bits of %cl/%ecx
call printf
movl -4(%rbp), %ecx
movl $-1, %esi
shrl %cl, %esi
call printf
这篇关于按位的意外行为使用gcc移的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!