MATLAB® Coder™, Simulink® Кодер и Embedded Coder® сгенерировать код С, который использует операторы shift left на C языке < < и shift right > >. Современные компиляторы C обеспечивают согласованное поведение операторов shift. Однако некоторые виды поведения операторов сдвига не полностью определены некоторыми стандартами C. Когда вы работаете с The MathWorks® продукты генерации кода, вам нужно знать, как управлять использованием сдвигов.
Дополнение двух является способом интерпретации двоичного числа. Большинство современных процессоров представляют целые числа, используя дополнение двух. MathWorks® продукты генерации кода требуют, чтобы компиляторы C и C++ представляли целые числа со знаком, используя дополнение двух. Тулбоксы и документация MathWorks используют представление двух комплементов исключительно.
Основное различие между арифметическим сдвигом и логическим сдвигом является намерением. Арифметические сдвиги имеют математический смысл. Цель логических сдвигов состоит в том, чтобы перемещать биты вокруг, что делает их полезными только для беззнаковых целых чисел, используемых в качестве наборов битовых флагов.
Язык C не различает арифметические и логические сдвиги и предоставляет только один набор операторов сдвига. Когда продукты генерации кода MathWorks используют сдвиги на подписанных целых числах в сгенерированном коде, намерение всегда является арифметическим сдвигом. Для беззнаковых целых чисел нет обнаруживаемого различия в поведении между логическим и арифметическим сдвигами.
Арифметический сдвиг влево представляет умножение на степень 2.
a << b = a*2^b
Если значение, полученное умножением на 2 ^ b, слишком велико, то происходит переполнение. В случае переполнения идеальный ответ переносов вокруг по модулю 2 ^ n, чтобы соответствовать типу данных. Стандарт C90 задает поведение слева. На уровне битов b из бит смещаются с левого конца и отбрасываются. На правом конце < reservedrangesplaceholder0 > бит значения 0 сдвинуты. Стандарт не определяет различие между неподписанным и подписанным. Для обоих неподписанных и двух комплементов со знаком, поведение на битовом уровне обеспечивает предполагаемое арифметическое поведение слева-сдвига.
Стандарт C99 описывает арифметическую интерпретацию. В нем также указывается, что для подписанных типов поведение не определено для любого отрицательного значения или для положительного значения, которое переполнено. Поставщик компилятора может использовать C99 стандартное предложение неопределенного поведения, чтобы оптимизировать код таким образом, чтобы изменить поведение, задуманное кодером. Если ваш компилятор C99-compliant, но не C90-compliant, отключите опцию Заменить умножения на степени двойки со знаковыми побитовыми сдвигами (Embedded Coder). Старые стандарты C++ соответствуют C90 стандарту в отношении смены налево. Более новые стандарты C++ аналогичны C99 стандарту.
Арифметический сдвиг вправо представляет деление на степень 2, где идеальный частный округляет в пол.
a >> b = a/2^b
Когда a неотрицательна, стандарты C заявляют, что правый сдвиг должен обеспечить это арифметическое поведение. Если a подписан и отрицателен, то стандарт утверждает, что реализация определяет поведение. Стандарт C требует, чтобы компиляторы документировали поведение их реализации. Почти все компиляторы реализуют сдвиг со знаком вправо как арифметический сдвиг, который округляется до этажа. Это самое простое и эффективное поведение для поставщика компилятора. Если у вас есть компилятор, который не предоставляет арифметический right-shift, или ваши стандарты кодирования не позволяют вам использовать signed right-shift, то можно выбрать опции, которые избегают signed shift right. Для примера Allow right сдвигов on signed целых чисел (Embedded Coder) заменяет signed right сдвигов на вызов функции.
В C при сдвиге целого числа < reservedrangesplaceholder1 > размеры слова используйте величину сдвига между 0 и n - 1 включительно. Стандарт C не определяет перемену на другие суммы, такие как:
Смещение на отрицательную константу.
Смещение на величину, большую, чем размер слова.
Когда величина сдвига постоянна, продукты не генерируют сдвиги вне области допустимого. Риск сдвигов вне области значений исходит из явно смоделированных сдвигов, где величина сдвига является непостоянной переменной. При моделировании сдвигов с переменными суммами сдвига убедитесь, что величина сдвига всегда находится в области значений.
Существуют явные и неявные источники сдвигов в моделях и алгоритмах.
Явный
Блок Shift Arithmetic Simulink
Stateflow® битовые операции
Неявный
Операции с фиксированной точкой, которые включают изменение масштаба
При преобразовании масштабирования с фиксированной точкой, если изменение наклона сети не является точной степенью двойки, то умножение, за которым следует сдвиг, аппроксимирует идеальный наклон сети. Для получения дополнительной информации о расчете уклона сети см. Указатель Расчета уклона сети.
Базовые алгоритмы более высокого уровня (для примера, БПФ алгоритмов)
Несколько параметров конфигурации влияют на количество и стиль сдвигов, которые появляются в сгенерированном коде.
Подписанные целочисленные раунды деления на
Установите этот параметр равным Floor
или Zero
чтобы избежать дополнительного сгенерированного кода.
Используйте деление для расчета наклона сети с фиксированной точкой
Когда это включено, этот параметр использует деление вместо умножения, за которым следуют сдвиги, чтобы выполнить расчет наклона сети с фиксированной точкой.
Замените умножения на степени двойки на подписанные битовые сдвиги (Embedded Coder)
Когда этот параметр включен, умножения на степени двойки заменяются на знаковые побитовые сдвиги. Очистка этой опции поддерживает MISRA C® податливость.
Разрешить правые сдвиги на подписанных целых числах (Embedded Coder)
Когда этот параметр включен, сгенерированный код может содержать правые побитовые сдвиги на подписанных целых числах. Чтобы предотвратить правильные побитовые сдвиги на целых числах со знаком, очистите эту опцию.
Сдвиньте вправо на целое число со знаком как арифметический сдвиг
Выберите этот параметр, если компилятор C реализует целое число правый сдвиг со знаком арифметики.