Home > Mobile >  bits shift exceeding width of type in C
bits shift exceeding width of type in C

Time:11-01

I have a uint64_t variable called vpn and I'm trying to get its left 9 bits. I know vpn is 45 bits long, so I tried the following:

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

but I get the following warning:

left shift count >= width of type

Why is that? 511 is 9 ones in binary so 511 << 36 should give me 45 bits, and I'm doing an AND with a uint64_t so the result should not exceed 64 bits..

Thank you!

CodePudding user response:

The constant 511 has type int. Your system most likely has a 32-bit int, so this means you're shifting a value by an amount larger than its bit length. Doing so triggers undefined behavior.

This is dictated by section 6.5.7p3 of the C standard regarding bitwise shift operators:

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.

You can fix this by using the ULL suffix on the constant, which will give it type unsigned long long which is guaranteed to be 64 bits in length.

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

CodePudding user response:

integer constants without any suffixes or prefixes have type of int. On many systems int is 32bit long, but it can also be only 16bits long (avr port).

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;
}
  • Related