Подтвердить что ты не робот

Bitshift и целое продвижение?

Обычно C требует, чтобы бинарные операнды операторов продвигались к типу операнда более высокого ранжирования. Это можно использовать, чтобы избежать заполнения кода с помощью verbose casts, например:

if (x-48U<10) ...
y = x+0ULL << 40;

и др.

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

int x = 1;
unsigned long long y = x << 32ULL;

Я бы ожидал, что тип правого операнда приведет к тому, что левый операнд будет продвинут на unsigned long long, чтобы сдвиг был успешным. Но вместо этого gcc печатает предупреждение:

warning: left shift count >= width of type

Является ли gcc сломанным, или стандарт делает какое-то исключение для правил продвижения типов для бит-брейков?

4b9b3361

Ответ 1

Так называемые обычные арифметические преобразования применяются ко многим бинарным операторам, но не ко всем из них. Например, они не применяются к операторам сдвига битов, операторам amp;, ||, запятой и операторам присваивания. Это правило для операторов сдвига бит:

6.5.7... 3 Семантика...
Целочисленные рекламные акции выполняются на каждом из операндов. Тип результата - это продвинутый левый операнд. Если значение правильного операнда отрицательное или больше или равно ширине продвинутого левого операнда, поведение undefined.

Ответ 2

Беда в том, что продвижение по службе работает только до того, что ваша платформа определяет как int. Как уже говорили некоторые другие ответы, оператор бит-сдвига будет продвигать левый операнд в int. Однако здесь int определяется как 32-битное значение. Целочисленное преобразование не будет распространяться на long long (64-разрядный).

Ответ 3

Вот что я нашел на эту тему:

  • Операторы побитового сдвига перемещают битовые значения двоичного объекта.
  • Левый операнд указывает значение, которое должно быть смещено.
  • Правый операнд определяет количество позиций, на которые биты в значении должны быть сдвинуты.
  • Результат не lvalue.

Оба операнда имеют одинаковый приоритет и являются ассоциативными слева направо. Каждый операнд должен иметь тип целого или перечисления. Компилятор выполняет интегральное продвижение над операндами, а затем правый операнд преобразуется в тип int. Результат имеет тот же тип, что и левый операнд (после арифметических преобразований).

Правый операнд не должен иметь отрицательного значения или значения, которое больше или равно ширине в битах смещаемого выражения. Результат побитовых сдвигов на таких значениях непредсказуем.

Если правый операнд имеет значение 0, результатом является значение левого операнда (после обычных арифметических преобразований). Оператор << заполняет освобожденные биты нулями.

Например, если left_op имеет значение 4019, битовая комбинация (в 16-битном формате) left_op имеет вид:

0000111110110011

Выражение left_op << 3 дает:

0111110110011000

Выражение left_op >> 3 дает:

0000000111110110

Источник: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.3.0/com.ibm.zos.v2r3.cbclx01/bitshe.htm