C ++: определены ли сдвиги влево / вправо для отрицательных и больших значений? - PullRequest
2 голосов
/ 25 сентября 2011

Мой вопрос в C ++, определен ли следующий код? Некоторые из них? И если это так, что он должен делать в этих четырех сценариях?

word <<  100;
word >>  100;
word << -100;
word >> -100;

слово uint32_t

(Это для узкого места в трехмерном рендере освещения. Одно из самых незначительных улучшений в самом внутреннем цикле, которое я хочу сделать, - устранение ненужных условных вилок. Один из этих вилок проверяет, нужно ли делать сдвиг влево для нескольких 32-битных слов, как часть подсчета веса Хэмминга. Если левый сдвиг принимает абсурдные значения, проверки вообще не нужны)

Ответы [ 2 ]

10 голосов
/ 25 сентября 2011

В C ++ 0X черновик N3290, §5.8:

Поведение не определено, если правый операнд отрицательный, или больше или равно длине в битах повышенного левого операнд.

Примечание: приведенный выше абзац идентичен стандарту C ++ 03.

Итак, последние два не определены. Другие, я полагаю, зависят от того, подписан ли word или нет, если word имеет длину не менее 101 бита. Если word «меньше», чем 101 бит, применяется вышеизложенное и поведение не определено.

Вот следующие два раздела этого абзаца в C ++ 0X (они отличаются в C ++ 03):

Значение E1 << E2 - это биты E2, сдвинутые влево E1; освобожденные биты заполнены нулями. Если E1 имеет неподписанный тип, значение результата равно E1 × 2E2, уменьшено по модулю на единицу больше максимально представимого значения в типе результата. В противном случае, если E1 имеет тип со знаком и неотрицательное значение, а E1 × 2E2 представимо в типе результата, то это итоговое значение; в противном случае поведение не определено. </p>

Значение E1 >> E2 - это биты E2, сдвинутые вправо E1. Если E1 имеет тип без знака или E1 имеет подпись тип и неотрицательное значение, значение результата является неотъемлемой частью отношения E1 / 2E2. Если Е1 имеет тип со знаком и отрицательное значение, результирующее значение определяется реализацией.

7 голосов
/ 25 сентября 2011

Стандарт C не указывает, что должно происходить, когда счетчик сдвига отрицателен или больше (или даже равен) точности переменной.

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

С аппаратным обеспечением x86 оператор сдвига использует только последние 5 бит счетчика сдвига, чтобы определить величину сдвига (это можно увидеть, прочитав справочное руководство CPU ), так что это, скорее всего, произойдет любой компилятор C или C ++ на этой платформе.

См. Также этот ответ для аналогичного вопроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...