Мне нужно проверить спецификацию на вопрос, что именно зависит от реализации.
Однако каждая реализация, которую я использовал (бормотал) годы проектов встраиваемых систем, была разумной:
Сдвиг влево всегда сдвигается в 0 на младшем бите. Никакое другое значение не имеет смысла.
Сдвиг вправо зависит от типа данных. Сдвиг вправо целого числа со знаком дублирует старший бит, поскольку он сдвигает остаток вправо. Это называется «арифметическим сдвигом» и обладает свойством nice (по крайней мере, в арифметике с двойным дополнением) делить значение на два, сохраняя при этом знак исходного числа.
Правое смещение целого числа без знака сдвигает 0 в старший бит и обычно называется «логическим сдвигом».
Имеет смысл для реализации обеспечить оба вида сдвигов, потому что оба полезны, и использование подписанного / беззнакового для выбора, что подразумевается, является разумным выбором.
Редактировать: По крайней мере, одна вещь, которая абсолютно зависит от реализации, - это то, что стандарт C не (полностью) не определяет базовую реализацию целых чисел и их хранилище. Например, можно создать совместимый C-компилятор для машины, которая использует свою арифметику дополнения. Также было бы возможно (я думаю) создать совместимый компилятор для машины, чье собственное хранилище было BCD со знаком величины. (Нет, я был неправ, см. Ниже.)
На практике мир в значительной степени основывается на двоичном комплементе для процессора, а часть педантичности обсуждается.
Таким образом, часть вопроса на самом деле такова: как вы определяете значение операторов << и >> таким образом, чтобы он был устойчивым независимо от используемой базовой арифметической системы.
IIRC, определение n<<1
эффективно n*2
, а n>>1
эффективно n/2
, с естественным расширением до сдвигов более чем на 1 (но не более 31 ... могут быть неопределенные драконы там ...) и с мыслью, что оператор >>
сохранит знак при работе со значением со знаком.
Редактировать 2: Пит Киркхам в своем прекрасном ответе указывает, что стандарт C специально запрещает страшный случай представления целых чисел в BCD, независимо от того, является ли оно величиной со знаком или дополнением к десяти. Я уверен, что это хорошо, даже если Кнут действительно использовал (необязательно) BCD-машину для своего примера кода в ранних выпусках Искусство компьютерного программирования .
В тех редких случаях использования, когда BCD является правильным ответом, затем сохраните их в беззнаковом длинном (8-значное десятичное дополнение) или 64-разрядном целом без знака (место для 16-значного десятичного дополнения или 15-значный плюс и знак и флаги) и использование тщательно созданной арифметической библиотеки для манипулирования ими имеет смысл.
На практике, разумеется, реализации на С отображают операторы так, как это прямо разрешено стандартом, для собственных машинных инструкций ЦП. Люди, которые написали стандарт, были очень помнящими о существовании многих способов реализовать даже простые вещи, такие как представление интегрального значения, и стандарт C отражает это, позволяя только достаточно определенному реализацией поведению позволить Операторы будут эффективно внедрены в каждую машину.
Альтернатива быстро ведет в мир, где все математические операции полностью определены и не могут быть эффективно реализованы ни на одной машине.