Вопросы | c

Являются ли операторы сдвига (<<, >>) арифметическими или логическими в C?

Вопрос

littlebyte | 201875 просмотров | рейтинг: 0

В C операторы сдвига (<<, >> ) арифметические или логические?

Комментарии:

Ciro Santilli 新疆改造中心 六四事件 法轮功

В чем смысл арифметики и логики? Связанный вопрос для подписанных целых:




Ответы

Mike Stone

+ 115 -
При сдвиге влево нет разницы между арифметическим и логическим сдвигом. При смещении вправо тип смещения зависит от типа смещаемого значения. (В качестве фона для тех читателей, которые не знакомы с разницей, логическое смещение вправо на 1 бит сдвигает все биты вправо и заполняет самый левый бит на 0. Арифметическое смещение оставляет исходное значение в крайнем левом бите. Разница становится важно при работе с отрицательными числами.) При смещении значения без знака оператор >> в C является логическим сдвигом. При смещении значения со знаком оператор >> является арифметическим сдвигом. Например, предположим, что 32-битный компьютер:
 signed int x1 = 5;
assert((x1 >> 1) == 2);
signed int x2 = -5;
assert((x2 >> 1) == -3);
unsigned int x3 = (unsigned int)-5;
assert((x3 >> 1) == 0x7FFFFFFD);
 

 


Ronnie

+ 82 -
Согласно 2-му изданию KR, результаты зависят от реализации правильных сдвигов подписанных значений. Википедия говорит, что C / C ++ «обычно» реализует арифметический сдвиг в знаковых значениях. По сути, вам нужно либо протестировать свой компилятор, либо не полагаться на него. Моя справка VS2008 для текущего компилятора MS C ++ говорит, что их компилятор выполняет арифметическое изменение.  


Greg Hewgill

+ 4 -
Ну, я посмотрел это в Википедии, и у них есть это, чтобы сказать:
  С, однако, имеет только один правый сдвиг   оператор, >>. Многие компиляторы C выбирают   какой сдвиг вправо выполнять в зависимости   на какой тип целого числа в настоящее время   сдвинуты; часто целые числа со знаком   сдвиг с использованием арифметического сдвига,   и целые числа без знака сдвинуты   используя логический сдвиг.
Похоже, это зависит от вашего компилятора. Также в этой статье обратите внимание, что сдвиг влево одинаков для арифметики и логики. Я бы порекомендовал сделать простой тест с несколькими знаковыми и беззнаковыми числами на границе (конечно, с набором старших битов) и посмотреть, каков результат на вашем компиляторе. Я также рекомендовал бы избегать зависимости от того, является ли он одним или другим, так как кажется, что C не имеет стандарта, по крайней мере, если это разумно и возможно избежать такой зависимости.  


Nick

+ 16 -
С точки зрения типа сдвига, который вы получаете, важен тип значения, которое вы сдвигаете. Классический источник ошибок - это когда вы переводите литерал, скажем, для маскировки битов. Например, если вы хотите удалить самый левый бит целого числа без знака, то вы можете попробовать это в качестве маски:
 ~0 >> 1
 

К сожалению, это доставит вам неприятности, потому что в маске будут установлены все биты, потому что смещаемое значение (~ 0) подписано, поэтому выполняется арифметическое смещение. Вместо этого вы захотите вызвать логический сдвиг, явно объявив значение как unsigned, то есть сделав что-то вроде этого:
 ~0U >> 1;
 

 


Cristián Romo

+ 0 -
gcc обычно использует логические сдвиги для переменных без знака и для сдвигов влево для переменных со знаком. Арифметическое смещение вправо является действительно важным, потому что оно будет подписывать расширение переменной. gcc будет использовать это, когда это применимо, как и другие компиляторы.  


asifaftab87

+ 0 -
Сдвиг влево <<). Но при сдвиге вправо >> мы должны следовать одному дополнительному правилу, и это правило называется копированием знака. Значение знака битового копирования состоит в том, что если старший значащий бит (LSB) установлен, то после повторного сдвига вправо снова будет установлен LSB, если он был сброшен, то он снова сбрасывается , означает, что если предыдущее значение было равно нулю, то после повторного сдвига бит равен нулю, если предыдущий бит был равен единице, а после сдвига он снова равен единице. Это правило не применимо для левого смещения. Самый важный пример для правого сдвига, если вы сдвигаете любое отрицательное число в правое смещение, то после некоторого сдвига значение, наконец, достигает нуля, а затем после этого, если сдвигать это -1, любое количество раз, значение будет оставаться тем же. Пожалуйста, проверьте.  


Alok Prasad

+ 0 -
GCC делает для -ve -> Арифметический сдвиг For + ve -> Logical Shift


Теги

c | binary | bit-manipulation | bit-shift

Похожие вопросы:

Арифметическое смещение битов на целых числах со знаком