Сдвиги битов в С - PullRequest
       17

Сдвиги битов в С

1 голос
/ 17 марта 2009

Если битовая комбинация, соответствующая целому числу со знаком, сдвинута вправо, то

1   vacant bit will be filled by the sign bit   
2   vacant bit will be filled by 0  
3   The outcome is implementation dependent 
4   none of the above

Ответ на этот вопрос - 3-й вариант. Кто-нибудь может это объяснить,

Также дайте некоторую базовую идею о теории операторов левого и правого сдвига в программировании на Си. Например.

что заполняется на свободном бите, когда выполняется любая операция. Я проверил и заметил, что сдвиг влево заполняет свободный бит на 0, а сдвиг вправо - на 1. Пожалуйста, очистите логику ...

Ответы [ 5 ]

5 голосов
/ 17 марта 2009

Мне нужно проверить спецификацию на вопрос, что именно зависит от реализации. Однако каждая реализация, которую я использовал (бормотал) годы проектов встраиваемых систем, была разумной:

  • Сдвиг влево всегда сдвигается в 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 отражает это, позволяя только достаточно определенному реализацией поведению позволить Операторы будут эффективно внедрены в каждую машину.

Альтернатива быстро ведет в мир, где все математические операции полностью определены и не могут быть эффективно реализованы ни на одной машине.

5 голосов
/ 17 марта 2009

C не гарантирует наличия знакового бита или чего-либо в представлении целых чисел на уровне битов, поэтому.

Для дополнения до двух вы обычно будете видеть сдвиг знака, но это зависит от реализации.

2 голосов
/ 17 марта 2009

ISO C99 требует знаковый бит где-то в представлении, но дает возможность выбора между различными схемами комплемента / знака и величины и допускает заполнение битов, которые влияют на работу >>.

Раздел 6.2.6.2 (целочисленные типы)

Для целочисленных типов со знаком биты представления объекта должны быть разделены на три группы: биты значения, биты заполнения и знак немного. Там не должно быть никаких битов заполнения; должен быть ровно один бит знака.

и

Раздел 6.5.7 (Операции побитового сдвига)

Результатом E1 >> E2 является E1-сдвинутая вправо позиция бита E2. Если E1 имеет тип без знака или E1 имеет тип со знаком и неотрицательный значение, значение результата является неотъемлемой частью отношения E1 / 2 E2 . Если E1 имеет тип со знаком и отрицательное значение, результирующее значение определяется реализацией.

В нем не указывается, какой из комплимента 1, комплимента 2 или знака и величины используется, а также, является ли бит знака левым или правым от битов значения, или где есть какое-либо дополнение, все это будет влиять на вывод оператор >> на подписанных негативах.

В ответ на запрос RBerteig C99 исключает представление целых чисел в BCD:

Раздел 6.2.6.2 (целочисленные типы)

Если имеется N битов значения, каждый бит должен представлять различную степень 2 от 1 до 2 N -1, так что объекты этого типа должны быть способен представлять значения от 0 до 2 N - 1, используя чистый двоичный файл представление; это должно быть известно как представление значения.

0 голосов
/ 17 марта 2009

Результат зависит от реализации. Однако на практике каждый отдельный компилятор x86, PPC и MIPS, с которым я когда-либо работал, следовал этому правилу для смещения вправо:

  1. Если операндом является целое число со знаком, свободный бит заполнен знак бит (действительно самый значащий бит)

  2. Если операнд целое число без знака, свободный бит заполнено нулями.

Как говорит Р.Бертайг, это так, что для знаковых целых чисел n >> 1 = n / 2 (округлено вниз ) как для положительного, так и отрицательного n, а также для без знака целые числа, n >> 1 = n / 2 даже для n> 2 ^ 31 (в 32-разрядной архитектуре).

Соответствующими аппаратными инструкциями являются арифметическое (расширение знака) и логическое (не расширение знака) смещение; компилятор выбирает между ними в зависимости от того, является ли операнд подписанным или беззнаковым.

0 голосов
/ 17 марта 2009

Реализации языка Си стремятся отобразить операции сдвига битов непосредственно на соответствующие инструкции машинного кода. Поскольку разные аппаратные архитектуры исторически делали разные вещи, спецификация C имеет тенденцию оставлять реализацию вещей определенной, чтобы реализации C могли использовать все, что предлагает оборудование.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...