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

Правильное смещение undefined, если число больше ширины типа?

Я только что проверил стандарт С++. Кажется, что следующий код НЕ должен быть undefined поведение:

unsigned int val = 0x0FFFFFFF;
unsigned int res = val >> 34;  // res should be 0 by C++ standard,
                               // but GCC gives warning and res is 67108863

И из стандарта:

Значение E1 → E2 - это позиции E1 с правым сдвигом E1. Если E1 имеет неподписанный тип или если E1 имеет подписанный тип и неотрицательный значение, значение результата является неотъемлемой частью частного E1/2 ^ E2. Если E1 имеет подписанный тип и отрицательное значение, результат значение определяется реализацией.

Согласно стандарту, поскольку 34 НЕ является отрицательным числом, переменная res будет равна 0.

GCC дает следующее предупреждение для фрагмента кода, а res - 67108863:

предупреждение: количество сдвигов вправо >= ширина типа

Я также проверил код сборки, выпущенный GCC. Он просто вызывает SHRL, а документ инструкции Intel для SHRL, res не является ZERO.

Значит ли это, что GCC не реализует стандартное поведение на платформе Intel?

4b9b3361

Ответ 1

проект стандарта С++ в разделе 5.8 Операторы сдвига в параграфе 1 говорят (внимание мое):

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

Итак, если unsigned int is 32 bits или меньше, то это undefined, что является точно предупреждением, которое дает gcc.

Ответ 2

Чтобы точно объяснить, что происходит: Компилятор загрузит 34 в регистр, а затем вашу константу в другой регистр и выполнит операцию правого сдвига с этими двумя регистрами. Процессор x86 выполняет "shiftcount% bits" в значении сдвига, что означает, что вы получаете сдвиг вправо на 2.

А так как 0x0FFFFFFF (268435455 десятичный) делится на 4 = 67108863, то результат вы видите.

Если у вас был другой процессор, например PowerPC (я думаю), он может дать вам нуль.