Warum wird ein vorzeichenloses Int des Bitfelds nach einer Verschiebungsoperation in C ++ zu einem vorzeichenbehafteten Int? [Duplikat]
Der Testcode:
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;
}
Die Ausgabe ist : -65536
, und der Typ b
ist int
aber nicht uint32_t
.
Ich habe das gefunden uint16_t
und uint8_t
werde auch nach dem Schichtoperator int signiert, und es gab eine ähnliche Frage in C#
, die zu dem Schluss kam, dass das Ergebnis signiert werden würde, wenn der Operand <32 Bit ist. Warum führen Verschiebungsoperationen immer zu einem vorzeichenbehafteten int, wenn der Operand <32 Bit ist?
Aber die Art von a.lo
ist klar uint32_t
, was überprüft werden kann decltype(a.lo)
, also wie kann dies erklärt werden?
Antworten
Es ist Teil der standardmäßigen integralen Werbung.
[Ausdrucksverschiebung]
1 Die Schichtoperatoren
<<
und die>>
Gruppe von links nach rechtsDie Operanden müssen vom Typ integraler oder nicht skalierter Aufzählung sein, und es werden integrale Promotionen durchgeführt. Der Typ des Ergebnisses ist der des heraufgestuften linken Operanden.
[conv.prom]
5 Ein Wert für ein integrales Bitfeld ([class.bit]) kann in einen Wert vom Typ konvertiert werden,
int
wennint
alle Werte des Bitfelds dargestellt werden können. Andernfalls kann es inunsigned int
if konvertiert werden,unsigned int
das alle Werte des Bitfelds darstellen kann. Wenn das Bitfeld noch größer ist, gilt keine integrale Heraufstufung. Wenn das Bitfeld einen Aufzählungstyp hat, wird es für Heraufstufungszwecke wie jeder andere Wert dieses Typs behandelt.
Die Heraufstufung Ihres linken Operanden (des Bitfelds) erzeugt ein int
, und das ist der Typ des gesamten Verschiebungsausdrucks. Somit b
handelt es sich auch um einen int
Abzug vom Platzhaltertyp.