В моем коде у меня много variable <<= 1;
где variable
имеет тип uint16_t. Компилятор выскакивает предупреждением.
преобразование в ‘uint16_t’ из ‘int’ может изменить его значение [-Wconversion]
Как я могу это решить? Я мог бы использовать длинную форму, такую как variable = (uint16_t)(variable << 1)
но я хотел бы сохранить короткую нотацию.
Основываясь на моем чтении стандарта, вы не можете уйти от этого предупреждения по этой причине:
uint16_t foo; foo <<= 1;
эквивалентно
uint16_t foo; foo = foo << 1;
Однако это уловлено в мире «целостного продвижения».
Значение выражения « foo << 1
» имеет тип « foo
», однако перед тем, как левый сдвиг может быть проведен, он сначала должен пройти «целую рекламу»; раздел 6.3.1.1.2 стандарта C99 указывает: «если int может представлять все значения исходного типа, значение преобразуется в int».
Это делает неявную версию вашего кода (с дополнительными скобками) следующим образом:
uint16_t foo; foo = ((int)foo) << 1;
Учитывая, что вы находитесь в системе с 32 или 64-битными ints (или чем-то большим, чем 16, действительно), вы действительно ставите большее значение в меньшую.
Один из способов этого - четко указать ваши броски следующим образом:
uint16_t foo; foo = (uint16_t)(foo << 1);
Но это означает, что нет, вы не можете использовать более короткий оператор присваивания побитового сдвига.
Если вы действительно делаете это в кучу, подумайте о том, чтобы создать вспомогательную функцию, которая делает ваш код понятным и компилируется.
void LS(uint16_t &value, int shift) { // LS means LeftShift *value = (uint16_t)(*value << shift); } LS(&foo, 1);
TL; DR: Нет, вы не можете использовать короткий оператор и одновременно избегать этого предупреждения.
Вы получаете предупреждение, потому что variable <<= 1;
эквивалентно:
variable = variable << 1;
где правая сторона имеет тип int
, а не uint16_t
, из-за целочисленных рекламных акций по умолчанию. Лучше всего это не использовать типы меньшего размера.