Правильное изменение неопределенного поведения, если число больше ширины типа?

Я просто проверил стандарт 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а кода, а res67108863 :

предупреждение: правое смещение> ширина ширины

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

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

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

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

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

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

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

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

  • Список стандартных длин для полей базы данных
  • Каковы новые возможности в C ++ 17?
  • Почему компиляторы позволяют строковым литералам не быть const?
  • Подготовка к std :: iterator Будучи устаревшим
  • Разница между void main и int main?
  • C ++ Метод статического члена вызывает экземпляр classа
  • Использование Unicode в исходном коде на C ++
  • Соглашения о кодировании - перечисление имен
  • Возьмите адрес элемента массива «один конец прошлого» через индекс: легальный по стандарту C ++ или нет?
  • Порядок оценки в параметрах функции C ++
  • Используйте CSS для автоматического добавления звездочки «обязательное поле» для формирования входных данных
  • Interesting Posts

    Внутреннее соединение DataTables в C #

    MVC5 – Как установить «selectedValue» в DropDownListFor Html helper

    Iphone – Как шифровать NSData с открытым ключом и расшифровывать с помощью закрытого ключа?

    Как установить приложение Cocoa в качестве браузера по умолчанию?

    Spring-Data FETCH JOIN with Paging не работает

    Ошибка: не был указан указатель по умолчанию и не было добавлено расширение

    Spark sql как взорваться без потери нулевых значений

    Почему Windows требует перезагрузки намного больше, чем Linux?

    Как передать ссылку на переменную стека в stream?

    пользовательские сообщения об ошибках с формой модели

    WooCommerce: добавляется плата за карточку на основе выбранного платежного шлюза

    Ошибка Powershell v3 Invoke-WebRequest HTTPS

    Как определить примитивный тип примитивной переменной?

    Как вы определяете, что такое «хороший» монитор?

    Доступ к содержимому R.string с использованием переменной для представления имени ресурса

    Давайте будем гением компьютера.