c++ - 为什么在C ++中进行移位操作后,位字段的无符号整数会变成有符号整数?

xxh*_*hxx 5 c++ language-lawyer

测试代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

输出是:-65536,类型bint但不是uint32_t

我发现,uint16_t并且uint8_t在移位运算符之后也会变成有符号整数,并且在 中有一个类似的问题C#,得出的结论是当操作数<32位时结果会变成有符号。 为什么当操作数小于 32 位时,移位操作总是产生有符号整数

但是 的类型a.lo是明确的uint32_t,可以通过 验证decltype(a.lo),那么这怎么解释呢?

Sto*_*ica 7

它是标准积分促销的一部分。

[表达式移位]

1移位运算符<<>>组从左到右

操作数应为整数或无作用域枚举类型,并执行整数提升。结果的类型是提升的左操作数的类型。

[转化率.prom]

5整型位域 ([class.bit]) 的纯右值可以转换为类型的纯右值,int如果int可以表示位域的所有值;否则,它可以转换为unsigned intif unsigned int可以表示位域的所有值。如果位字段更大,则没有积分提升适用于它。如果位字段具有枚举类型,则出于提升目的,将其视为该类型的任何其他值。

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