位移位超过 C 中类型的宽度

bits shift exceeding width of type in C

我有一个名为 vpn 的 uint64_t 变量,我正在尝试获取它的左 9 位。 我知道 vpn 是 45 位长,所以我尝试了以下操作:

uint64_t nineMSB = (vpn & (511 << 36)) >> 36;

但我收到以下警告:

left shift count >= width of type

这是为什么? 511 在二进制中是 9 个所以 511 << 36 应该给我 45 位,我正在用 uint64_t 做一个 AND 所以结果不应该超过 64 位..

谢谢!

常量 511 的类型为 int。您的系统很可能有一个 32 位 int,因此这意味着您要将一个值移动一个大于其位长度的量。这样做会触发 undefined behavior.

这是由 C standard 的第 6.5.7p3 节关于位移运算符的规定:

The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. 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.

您可以通过在常量上使用 ULL 后缀来解决此问题,这将赋予它 unsigned long long 类型,保证长度至少为 64 位。

uint64_t nineMSB = (vpn & (511ULL << 36)) >> 36;

没有任何后缀或前缀的整数常量的类型为 int。在许多系统上 int 是 32 位长,但它也可以只有 16 位长(avr 端口)。

uint64_t foo(uint64_t vpn)
{
    uint64_t nineMSB = (vpn & (511ULL << 36)) >> 36;
    return nineMSB;
}

uint64_t foo1(uint64_t vpn)
{
    uint64_t nineMSB = (vpn & ((uint64_t)511 << 36)) >> 36;
    return nineMSB;
}