Por que um int não assinado do campo de bits se torna um int assinado após a operação de deslocamento em C ++? [duplicado]
O código de teste:
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;
}
A saída é: -65536
e o tipo de b
é, int
mas não uint32_t
.
Eu descobri isso, uint16_t
e uint8_t
também se tornará assinado int após o operador shift, e houve uma pergunta semelhante em C#
, que chegou à conclusão de que o resultado seria assinado quando o operando fosse <32 bits. Por que as operações de deslocamento sempre resultam em um int assinado quando o operando é <32 bits
Mas o tipo de a.lo
é claro uint32_t
, que pode ser verificado por decltype(a.lo)
, então como isso pode ser explicado?
Respostas
Faz parte da promoção integral padrão.
[expr.shift]
1 Os operadores de turno
<<
e>>
grupo da esquerda para a direitaOs operandos devem ser do tipo enumeração integral ou sem escopo e promoções integrais são realizadas. O tipo de resultado é o do operando esquerdo promovido.
[conv.prom]
5 Um prvalue para um campo de bits integral ([class.bit]) pode ser convertido em um prvalue do tipo
int
seint
puder representar todos os valores do campo de bits; caso contrário, pode ser convertido emunsigned int
ifunsigned int
pode representar todos os valores do campo de bits. Se o campo de bits for maior ainda, nenhuma promoção integral se aplica a ele. Se o campo de bits tiver um tipo enumerado, ele será tratado como qualquer outro valor desse tipo para fins de promoção.
A promoção de seu operando esquerdo (o campo de bits) produz um int
, e esse é o tipo de toda a expressão de deslocamento. Portanto, b
é uma int
dedução por tipo de espaço reservado.