为什么在 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;
}
输出是:-65536
,b
的类型是int
,不是uint32_t
。
我发现,uint16_t
和uint8_t
经过移位运算符后也会变成signed int,C#
也有类似的问题,得出的结论是当操作数小于 32 位时,结果将变为有符号。
Why do shift operations always result in a signed int when operand is <32 bits
但是a.lo
的类型明明是uint32_t
,decltype(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
占位符类型推导。
测试代码:
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;
}
输出是:-65536
,b
的类型是int
,不是uint32_t
。
我发现,uint16_t
和uint8_t
经过移位运算符后也会变成signed int,C#
也有类似的问题,得出的结论是当操作数小于 32 位时,结果将变为有符号。
Why do shift operations always result in a signed int when operand is <32 bits
但是a.lo
的类型明明是uint32_t
,decltype(a.lo)
可以验证,这怎么解释呢?
标准积分促销的一部分。
[expr.shift]
1 The shift operators
<<
and>>
group left-to-rightThe 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
ifint
can represent all the values of the bit-field; otherwise, it can be converted tounsigned int
ifunsigned 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
占位符类型推导。