Почему беззнаковое int битового поля становится подписанным int после операции сдвига в C ++? [дубликат]

Dec 15 2020

Код теста:

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

Вывод:, -65536а тип b- intно нет uint32_t.

Я обнаружил, что, uint16_tа uint8_tтакже станет подписанным int после оператора сдвига, и был аналогичный вопрос C#, который пришел к выводу, что результат станет подписанным, когда операнд <32 бит. Почему операции сдвига всегда приводят к подписанному int, если операнд <32 бит

Но тип a.loочевиден uint32_t, по которому можно проверить decltype(a.lo), так как это можно объяснить?

Ответы

7 StoryTeller-UnslanderMonica Dec 15 2020 at 20:01

Это часть стандартного комплексного продвижения.

[expr.shift]

1 Операторы сдвига <<и >>группировка слева направо

Операнды должны быть целочисленного типа или типа перечисления с незаданной областью, и выполняются целые рекламные акции. Тип результата - это тип продвинутого левого операнда.

[conv.prom]

5 Prvalue для целочисленного битового поля ([class.bit]) может быть преобразовано в prvalue типа, intесли intможет представлять все значения битового поля; в противном случае он может быть преобразован в unsigned intif, который unsigned intможет представлять все значения битового поля. Если битовое поле еще больше, к нему не применяется интегральное продвижение. Если битовое поле имеет перечислимый тип, оно рассматривается как любое другое значение этого типа в целях продвижения.

Продвижение вашего левого операнда (битового поля) производит int, и, таким образом, это тип всего выражения сдвига. Таким образом b, это intтоже вывод типа заполнителя.