Почему беззнаковое int битового поля становится подписанным int после операции сдвига в C ++? [дубликат]
Код теста:
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)
, так как это можно объяснить?
Ответы
Это часть стандартного комплексного продвижения.
[expr.shift]
1 Операторы сдвига
<<
и>>
группировка слева направоОперанды должны быть целочисленного типа или типа перечисления с незаданной областью, и выполняются целые рекламные акции. Тип результата - это тип продвинутого левого операнда.
[conv.prom]
5 Prvalue для целочисленного битового поля ([class.bit]) может быть преобразовано в prvalue типа,
int
еслиint
может представлять все значения битового поля; в противном случае он может быть преобразован вunsigned int
if, которыйunsigned int
может представлять все значения битового поля. Если битовое поле еще больше, к нему не применяется интегральное продвижение. Если битовое поле имеет перечислимый тип, оно рассматривается как любое другое значение этого типа в целях продвижения.
Продвижение вашего левого операнда (битового поля) производит int
, и, таким образом, это тип всего выражения сдвига. Таким образом b
, это int
тоже вывод типа заполнителя.