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]

Dec 15 2020

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 é: -65536e o tipo de bé, intmas não uint32_t.

Eu descobri isso, uint16_te uint8_ttambé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

7 StoryTeller-UnslanderMonica Dec 15 2020 at 20:01

Faz parte da promoção integral padrão.

[expr.shift]

1 Os operadores de turno <<e >>grupo da esquerda para a direita

Os 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 intse intpuder representar todos os valores do campo de bits; caso contrário, pode ser convertido em unsigned intif unsigned intpode 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 intdedução por tipo de espaço reservado.