Why does an unsigned int of bit-field become a signed int after shift operation in C++?

Viewed 197

The test code:

struct A
{
    uint32_t lo : 16;
    uint32_t hi : 16;
};

int main()
{
    A a{};
    a.lo = 0xFFFF;
    auto b = a.lo << 16;
    cout << b << endl;
    return 0;
}

The output is:-65536, and the type of b is int but not uint32_t.

I have found that, uint16_t and uint8_t will also become signed int after shift operator, and there was a similar question in C#, which came to the conclusion that the result would become signed when the operand is <32 bits. Why do shift operations always result in a signed int when operand is <32 bits

But the type of a.lo is clearly uint32_t, which can be verified by decltype(a.lo), so how can this be explained?

1 Answers

It's part of the standard integral promotion.

[expr.shift]

1 The shift operators << and >> group left-to-right

The operands shall be of integral or unscoped enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand.

[conv.prom]

5 A prvalue for an integral bit-field ([class.bit]) can be converted to a prvalue of type int if int can represent all the values of the bit-field; otherwise, it can be converted to unsigned int if unsigned int can represent all the values of the bit-field. If the bit-field is larger yet, no integral promotion applies to it. If the bit-field has an enumerated type, it is treated as any other value of that type for promotion purposes.

Promotion of your left operand (the bit-field) produces an int, and so that's the type of the entire shift expression. Thus b is an int too by placeholder type deduction.

Related