Неопределенное поведение сдвига вправо в C ++ - PullRequest
0 голосов
/ 04 октября 2018

От cppreference.com:

Для неподписанного a и для подписанного a с неотрицательными значениями значение a >> b является целой частью a / 2 b ,Для отрицательного значения a >> b определяется реализацией (в большинстве реализаций выполняется арифметическое смещение вправо, так что результат остается отрицательным).

В любом случае, если значение праваоперанд отрицательный или больше или равен числу битов в продвинутом левом операнде, поведение не определено.

Почему у нас неопределенное поведение, если правый операнд больше или равенколичество бит в повышенном левом операнде?Мне кажется, что результат должен быть 0 (по крайней мере, для беззнаковых / положительных целых чисел) ...

В частности, с g ++ (версия 4.8.4, Ubuntu):

unsigned int x = 1;
cout << (x >> 16 >> 16) << " " << (x >> 32) << endl;

дает: 0 1

Ответы [ 2 ]

0 голосов
/ 05 октября 2018

Чтобы привести конкретный пример, x86 обрезает число сдвигов до 5 бит (6 бит для 64-разрядных сдвигов), а ARM обрезает число сдвигов до 8 бит.В текущем стандарте C ++ компиляторы для обоих процессоров могут реализовывать сдвиги с помощью одного кода операции.

Если стандарт C ++ определит результат сдвигов более чем на длину операнда определенным образом, компиляторы нацелены как минимум на одиниз семейств процессоров (и, возможно, обоих, если результат, требуемый C ++, не будет соответствовать какой-либо аппаратной реализации, как, например, предложенное вами поведение), придется реализовывать каждую операцию сдвига с использованием ветвей, что приведет к требуемому результату, когда код операции CPU не будет 'т.

0 голосов
/ 04 октября 2018

Одна из целей C ++ - предоставить быстрый и эффективный код, «близкий к аппаратному».И на большинстве аппаратных средств, целое смещение вправо или влево может быть реализовано одним кодом операции.Проблема в том, что разные процессоры ведут себя по-разному в этом случае, когда величина сдвига больше, чем число битов.

Так что, если C ++ предписывает определенное поведение для операций сдвига, при создании кода для процессора, чье поведение кода операциине соответствует всем требованиям Стандарта, компиляторы должны будут вставлять проверки и логику, чтобы убедиться, что результат соответствует Стандарту во всех случаях.Это должно происходить почти во всех случаях использования встроенных операторов сдвига, если только оптимизатор не докажет, что угловой случай на самом деле не произойдет.Добавленные проверки и логика потенциально могут замедлить работу программы.

...