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]
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:, -65536
et le type de b
est int
mais pas uint32_t
.
J'ai trouvé cela, uint16_t
et uint8_t
je 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.lo
est clairement uint32_t
, ce qui peut être vérifié par decltype(a.lo)
, alors comment cela peut-il être expliqué?
Réponses
Cela fait partie de la promotion intégrale standard.
[expr.shift]
1 Les opérateurs de décalage
<<
et le>>
groupe de gauche à droiteLes 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
int
si elleint
peut représenter toutes les valeurs du champ binaire; sinon, il peut être converti enunsigned int
ifunsigned int
peut 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 b
une int
déduction par type d'espace réservé.