другой результат о побитовом операторе в C - PullRequest
1 голос
/ 09 августа 2011

, чтобы реализовать логический сдвиг вправо в c, я ищу в Интернете и получаю следующий код C

int a, b, c;
int x = -100;
a = (unsigned) x >> 2;
b = (0xffffffff & x) >> 2;
c = (0x0 | x ) >> 2;

, теперь и a, и b были логическим результатом сдвига вправо (1006632960), но c все еще былрезультат арифметического сдвига (-25) somebody кто-нибудь может объяснить, почему?ТНХ

Ответы [ 3 ]

1 голос
/ 09 августа 2011

(unsigned) x имеет тип unsigned int, поэтому он получает логический сдвиг.

0xffffffff (при условии, что 32-битное int) имеет тип unsigned int, поэтому (0xffffffff & x) также имеет тип unsigned int, поэтомуон получает логический сдвиг.

0x0 имеет тип int, поэтому (0x0|x) имеет тип int и получает арифметический сдвиг (ну, это зависит от реализации).

1 голос
/ 09 августа 2011
b = (0xffffffff & x) >> 2;

Предполагая, что ваши целые числа 32-битные, тип литеральной константы 0xffffffff равен unsigned int, потому что он слишком велик, чтобы поместиться в обычном int.&, тогда, находится между unsigned int и int, и в этом случае тип без знака выигрывает по определению.Следовательно, сдвиг происходит без знака;таким образом, он сдвигается на 0 бит слева.

c = (0x0 | x ) >> 2;

Тип 0x0 по умолчанию равен int, потому что он достаточно мал, чтобы соответствовать, поэтому побитовый или происходит в целых числах, и поэтомуследующая сменаЭто реализация, определяемая тем, что происходит, когда вы сдвигаете целое число со знаком вправо, но большинство компиляторов будет производить арифметическое смещение, расширяющее знак.

0 голосов
/ 09 августа 2011

Это все о типе операнда operator >>.Если это signed - сдвиг вправо устанавливает MSB в 1, если операнд был отрицательным.Если операнд равен unsigned - биты старшего бита всегда равны нулю после сдвига вправо.

В вашем первом выражении операнд явно приведен к unsigned.

Во втором выражении (0xffffffff & x) нас без знака, потому что 0xffffffff определенно представляет целое число без знака (это переполнение для signed).

OTOH в третьем примере 0x0 равно signed (это значение по умолчанию для целочисленных констант)).Следовательно, весь операнд (0x0 | x ) считается подписанным

...