Правильное изменение неопределенного поведения, если число больше ширины типа?
Я просто проверил стандарт C ++ . Кажется, что следующий код НЕ должен быть неопределенным поведением :
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 поправочные позиции E2 с правым сдвигом. Если E1 имеет неподписанный тип или если E1 имеет подписанный тип и неотрицательное значение, значение результата является неотъемлемой частью частного E1 / 2 ^ E2. Если E1 имеет подписанный тип и отрицательное значение, результирующее значение определяется реализацией.
Согласно стандарту, поскольку 34 НЕ является отрицательным числом, переменная res
будет равна 0.
GCC дает следующее предупреждение для fragmentа кода, а res
– 67108863
:
предупреждение: правое смещение> ширина ширины
Я также проверил код сборки, выпущенный GCC. Он просто вызывает SHRL
и документ инструкции Intel для SHRL, res
не является ZERO.
Значит ли это, что GCC не реализует стандартное поведение на платформе Intel?
- Почему стандартные iteratorы диапазона вместо ?
- Нет определенного типа параметра функции по умолчанию для int? Я сошел с ума?
- Как поместить элемент управления WebBrowser в IE9 в стандарты?
- Существуют ли машины, где sizeof (char)! = 1 или, по крайней мере, CHAR_BIT> 8?
- Почему неназванное пространство имен является «превосходной» альтернативой статическому?
- size_t всегда без знака?
- Когда функция имеет параметр массива определенного размера, почему она заменяется указателем?
- Является ли `long` гарантией быть как минимум 32 бит?
Проект стандарта С ++ в разделе 5.8
Операторы сдвига в параграфе 1 говорят ( акцент мой ):
Тип результата – это продвинутый левый операнд. Поведение не определено, если правый операнд отрицательный или больше или равен длине в битах продвинутого левого операнда .
Поэтому, если unsigned int равно 32 bits
или меньше, это не определено, что является именно предупреждением, которое gcc
дает вам.
Чтобы точно объяснить, что происходит: компилятор загрузит 34
в регистр, а затем вашу константу в другой регистр и выполнит операцию правого сдвига с этими двумя регистрами. Процессор x86 выполняет «shiftcount% bits» в значении сдвига, что означает, что вы получаете сдвиг вправо на 2.
А так как 0x0FFFFFFF (268435455 десятичный), деленный на 4 = 67108863, это результат, который вы видите.
Если бы у вас был другой процессор, например PowerPC (я думаю), он может дать вам нуль.