Поля заголовка не достаточно долго, чтобы взятие подробного вопроса, так и для записи, мой фактического вопрос определяет «неразумным» определенным образом:Может ли компилятор C реализовать подписанный сдвиг вправо «необоснованно»?
Законно для C имеют арифметическое право оператор сдвига, который возвращает разные результаты, со временем, для идентичных значений аргументов? То есть, должен
>>
быть истинным function?
Представьте, что вы хотели написать переносимый код, используя правильный сдвиг >>
подписанных значения в C. К сожалению, для вас, наиболее эффективной реализации некоторой критической части вашего алгоритма является самым быстрым, когда Подписанные правые сдвиги заполнить знаковый бит (т. е. они арифметические сдвиги вправо). Теперь, начиная с this behavior is implementation defined, вы отвратителен, если хотите написать переносимый код, который использует его.
Просто прочитав документацию компилятора (которую он должен предоставить в стандарте, но может или не может быть легко доступен или даже существует) отлично, если вы знаете все компиляторы, которые вы будете запускать на и будете когда-либо работайте на, но поскольку это часто невозможно, вы можете найти способ сделать это переносимо.
Один из способов я подумал о том, чтобы просто тесте поведения компилятора во время выполнения: это он появляется для реализации арифметического сдвига вправо, использовать оптимизированный алгоритм, но если не использовать запасной вариант, который не делает полагайтесь на это. Конечно, просто проверка того, что говорят, что (short)0xFF00 >> 4 == 0xFFF0
недостаточно, так как он не исключает, что возможно char
или int
значения работают по-другому или даже странный случай, когда он заполняет некоторые суммы или значения сдвига, но не для других .
Так что при условии, что комплексный подход будет исчерпывающим образом проверять все значения и величины сдвига. Для всех 8-битных char
входов, это только 2 значения LHS и 2 значения РИТ в общей сложности 2 , в то время как short
(обычно, но скажем int16_t
, если вы хотите быть педантичным) составляет только 2 , который может быть проверен на долю секунды на современном оборудовании . Выполнение всех 2 32-битные значения занимают несколько секунд на достойном оборудовании, но все же, возможно, разумны. Однако в обозримом будущем 64-битная версия.
Предположим, вы сделали это и обнаружили, что поведение >>
точно соответствует желаемому арифметическому сдвигу. Безопасно ли вам полагаться на него в соответствии со стандартом: стандартно ли ограничивает реализацию , чтобы не изменять его поведение во время выполнения? То есть поведение должно быть выражено как функция его входов, или может (short)0xFF00 >> 4
быть 0xFFF0
один момент, а затем 0x0FF0
(или любое другое значение) следующего?
Сейчас этот вопрос в основном теоретический характер, но нарушают это, вероятно, не так с ума, как это может показаться, учитывая наличие гибридных архитектур, таких как big.LITTLE, динамически перемещать процессы от на CPU к другому с возможными небольшими различиями в поведении , или живая миграция VM между чипами, производимыми Intel и AMD, с незначительными (обычно недокументированными) различиями в поведении инструкций.
Под «законным» я имею в виду согласно C стандарта, не в соответствии с законодательством вашей страны, конечно.
I.e., он реплицирует бит знака для вновь сдвинутых бит.
Это было бы вид с умом, но не , что с умом: х86 имеет различное поведение (переполнение битого флага настройки) для сдвигов 1, а не другие сдвигов, а также ARM масок величины сдвига в surprising way, что простой тест, вероятно, не обнаружит.
По крайней мере, ничего лучше микроконтроллера. Внутренний цикл проверки представляет собой несколько простых инструкций, поэтому процессор с тактовой частотой 1 ГГц может проверять все ~ 1 млн коротких значений в ~ 1 мс при одной инструкции за цикл.
Итак, вы в основном задаете вопрос, является ли поведение, определяемое реализацией, последовательным во всей реализации? Я бы сказал, это зависит. I случай * чистых * математических функций, таких как сдвиги, они не должны давать * никаких * побочных эффектов, и их результат должен зависеть только от значений операндов. В случае некоторых других функций без ограничения * чистоты, это может быть иначе .. –
В качестве побочного примечания ваше тестовое выражение с «коротким» является ошибочным. Все операции будут по крайней мере использовать тип, такой же широкий, как «int» в качестве базового типа. Приведение к «короткому», а затем перемещение ничего не покупает, оно по-прежнему «int». –
Более или менее это то, что я прошу - хотя мое точное состояние было даже немного более узким - может ли значение измениться в течение всего жизненного цикла одного процесса. Обратите внимание, что побочные эффекты не нужны для изменения поведения. Сам '>>' может быть без побочных эффектов, но что-то другое может измениться (не связано с каким-либо вызовом '>>'), которое влияет на последующие вызовы (я полагаю ...). – BeeOnRope