Warum wird ein vorzeichenloses Int des Bitfelds nach einer Verschiebungsoperation in C ++ zu einem vorzeichenbehafteten Int? [Duplikat]

Dec 15 2020

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 bist intaber nicht uint32_t.

Ich habe das gefunden uint16_tund uint8_twerde 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.loist klar uint32_t, was überprüft werden kann decltype(a.lo), also wie kann dies erklärt werden?

Antworten

7 StoryTeller-UnslanderMonica Dec 15 2020 at 20:01

Es ist Teil der standardmäßigen integralen Werbung.

[Ausdrucksverschiebung]

1 Die Schichtoperatoren <<und die >>Gruppe von links nach rechts

Die 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, intwenn intalle Werte des Bitfelds dargestellt werden können. Andernfalls kann es in unsigned intif konvertiert werden, unsigned intdas 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 bhandelt es sich auch um einen intAbzug vom Platzhaltertyp.