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

Я просто проверил стандарт 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 (я думаю), он может дать вам нуль.

  • Базовый указатель на массив производных объектов
  • Могут ли компиляторы исключать бесконечные петли?
  • Синтаксис JSON позволяет дублировать ключи в объекте?
  • Нужно ли избегать точки в classе символов (квадратные скобки) регулярного выражения?
  • Как определить версию стандарта C ++, используемую компилятором?
  • Предоставляет ли компилятор возможность переработать освобожденные переменные указателя?
  • Шестигранное представление цвета с альфа-каналом?
  • Препроцессор C ++ идентичен препроцессору C?
  • Эффекты ключевого слова extern для функций C
  • size_t всегда без знака?
  • Используйте CSS для автоматического добавления звездочки «обязательное поле» для формирования входных данных
  • Interesting Posts

    отправка нескольких форм с помощью AJAX

    Какие эффекты могут иметь ключевое слово virtual в Entity Framework 4.1 POCO Code First?

    Android Studio не удалось найти версию, совместимую с com.android.support:appcompat-v7:+

    Почему 248×248 максимальный размер двумерного массива, который я могу объявить?

    необходимо вызвать функцию с периодическими временными интервалами в c ++

    Как импортировать CSV-файлы в таблицу PostgreSQL?

    Динамические маршруты из базы данных для ASP.NET MVC CMS

    O (klogk) для нахождения k-го наименьшего элемента из двоичной кучи

    Удобный способ анализа входящих параметров multipart / form-data в Servlet

    FTP-скрипт не будет передавать удаленные файлы на локальный компьютер

    Как преобразовать трассировку стека в строку?

    Json.NET (Newtonsoft.Json) – Два «свойства» с таким же именем?

    XSL-FO: принудительная обертка на табличных записях

    Как усечь файл в C?

    Кварц: выражение Cron, которое никогда не будет выполнено

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