5

可能重复:
GCC 左移溢出

考虑以下最小程序。

#include <stdint.h>
#include <stdio.h>

int main()
{
    uint32_t v = 1024;
    v &= (((uint32_t)1 << 32) - 1);
    printf("v = %u\n", v);
    return 0;
}

正如1024我所期望的那样在 MinGW 下使用 GCC 进行编译。因为 1 向左移动 32 次又是 0,因此 0-1 = -1 即“1111....1111”。这个与任何值的 AND 应该再次返回相同的值。

但是,如果我将程序更改为

#include <stdint.h>
#include <stdio.h>

int main()
{
    unsigned int s = 32;
    uint32_t v = 1024;
    v &= (((uint32_t)1 << s) - 1);
    printf("v = %u\n", v);
    return 0;
}

现在打印的结果是0. 有人可以解释这种行为吗?

4

2 回答 2

7

将 32 位值移动 32 位是 C 中未定义的行为。不要这样做。

于 2012-08-06T15:44:32.180 回答
6

两者都是未定义的行为,因为移位距离必须小于类型的位宽。使用常量,gcc 的优化器会执行您期望的操作,但是使用变量,移位是在运行时完成的。移位距离可能被 31 所掩盖,因此没有进行移位并且 1 - 1 == 0。

于 2012-08-06T15:45:14.483 回答