Pourquoi un int non signé du champ de bits devient-il un int signé après une opération de décalage en C ++? [dupliquer]

Dec 15 2020

Le code de test:

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

La sortie est:, -65536et le type de best intmais pas uint32_t.

J'ai trouvé cela, uint16_tet uint8_tje deviendrai également signé int après l'opérateur de décalage, et il y avait une question similaire dans C#, qui est arrivée à la conclusion que le résultat deviendrait signé lorsque l'opérande est <32 bits. Pourquoi les opérations de décalage aboutissent-elles toujours à un entier signé lorsque l'opérande est <32 bits

Mais le type de a.loest clairement uint32_t, ce qui peut être vérifié par decltype(a.lo), alors comment cela peut-il être expliqué?

Réponses

7 StoryTeller-UnslanderMonica Dec 15 2020 at 20:01

Cela fait partie de la promotion intégrale standard.

[expr.shift]

1 Les opérateurs de décalage <<et le >>groupe de gauche à droite

Les opérandes doivent être de type énumération intégrale ou non et des promotions intégrales sont effectuées. Le type du résultat est celui de l'opérande gauche promu.

[conv.prom]

5 Une prvalue pour un champ binaire intégral ([class.bit]) peut être convertie en une prvalue de type intsi elle intpeut représenter toutes les valeurs du champ binaire; sinon, il peut être converti en unsigned intif unsigned intpeut représenter toutes les valeurs du champ de bits. Si le champ de bits est encore plus grand, aucune promotion intégrale ne s'applique à lui. Si le champ de bits a un type énuméré, il est traité comme toute autre valeur de ce type à des fins de promotion.

La promotion de votre opérande gauche (le champ de bits) produit un int, et c'est donc le type de l'expression de décalage entière. C'est donc bune intdéduction par type d'espace réservé.