2015-10-10 2 views
0

Под GCC, следующий код всегда возвращает левый операнд << если num1s == 0:сдвиг влево целое 32 бит

0xFFFFFFFFu << (32-num1s); 

После прочтения Why doesn't left bit-shift, "<<", for 32-bit integers work as expected when used more than 32 times?, и стандарт цитирует Дэвида Heffernan, кажется, что если левый операнд неподписанный, это определенная операция. Только когда E1 (левый операнд) имеет подписанный тип и неотрицательное значение, это может привести к неопределенному поведению.

Может ли кто-нибудь объяснить, если стандартные состояния явно, что если смещение суммы больше числа бит, которое содержит тип, это неопределенное поведение?

+0

«Поведение не определено, если правый операнд отрицательный или больше или равен длине в битах продвинутого левого операнда». но серьезно, получите себе копию стандарта, эти вопросы тривиальны, чтобы ответить самим. –

+0

Почему это было неопределенное поведение? Он очень определен, и операция приведет к '0'. – YePhIcK

+2

@YePhIcK Он не определен, потому что он определен. –

ответ

4

Операторы сдвига пункте 5.8

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

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

+0

Спасибо за цитату из стандарта. Есть ли бесплатный онлайн-C++ в Интернете? – Rich

+0

@Rich Вы можете получить его [здесь] (https://isocpp.org/std/the-standard). Завершенный стандарт должен быть приобретен, но вы можете получить черновик (который на 99% совпадает с окончательной версией) бесплатно на той же странице. – CoryKramer

1

CoryKramer ответил, почему это неопределенное поведение по стандарту.

Я попытаюсь выяснить, как это работает в реальной ситуации. Компиляторы C++ обычно используют операторы << и >> для 32-разрядных целых чисел в качестве инструкций ассемблера без проверки диапазона операндов. Это означает, что результат зависит от специфичной для процессора реализации команд сдвига.

Например, спецификация Intel процессор для инструкций 32-битный СХЛ/SHR/SAL/SAL говорит:

Адресат операнд может быть регистр или ячейку памяти. Оператор count может быть немедленным значением или зарегистрировать CL. Счетчик маскируется с пятью битами, что ограничивает диапазон счетчика на 0 до 31.

Это означает, что a << b становится a << (b & 0x1f) на процессорах Intel. Поэтому смещение на 32 бита означает отсутствие сдвига.

Но вы не должны полагаться на эту информацию! Компилятор также может оптимизировать код и реализовать оператор сдвига с помощью векторных инструкций. В этом случае поведение не определено даже по спецификациям процессора.

+0

Хорошая информация, чтобы знать. благодаря! – Rich

Смежные вопросы