为什么在 C++ 中,位域的无符号整数在移位操作后变成有符号整数?

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

测试代码:

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

输出是:-65536b的类型是int,不是uint32_t

我发现,uint16_tuint8_t经过移位运算符后也会变成signed int,C#也有类似的问题,得出的结论是当操作数小于 32 位时,结果将变为有符号。 Why do shift operations always result in a signed int when operand is <32 bits

但是a.lo的类型明明是uint32_tdecltype(a.lo)可以验证,这怎么解释呢?

标准积分促销的一部分。

[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.

左操作数(位域)的提升会产生一个 int,因此这就是整个移位表达式的类型。因此 b 也是 int 占位符类型推导。