Странное правое несоответствие сдвига битов - PullRequest
0 голосов
/ 21 сентября 2018

Я работал с битами в C (работает на Ubuntu).Используя два разных способа смещения целого числа вправо, я получил странно разные выходные данные:

#include <stdio.h>
int main(){
int x = 0xfffffffe;
int a = x >> 16;
int b = 0xfffffffe >> 16;
printf("%X\n%X\n", a, b);
return 0;
}

Я думаю, что выходные данные будут одинаковыми для каждого: FFFF, потому что четыре правильных шестнадцатеричных знака (16 бит)смещаются от человека.Вместо этого вывод:

FFFFFFFF
FFFF

Чем объясняется такое поведение?

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

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

Следовательно,

int x = 0xfffffffe;
int a = x >> 16;

эта часть выполняет арифметическое смещение, потому что x подписано .И поскольку x на самом деле отрицательный (-2 в дополнении к двум), x означает знак расширения , поэтому добавляются '1', что приводит к 0xFFFFFFFF.

Наоборот,

int b = 0xfffffffe >> 16;

0xfffffffe - это буква, интерпретируемая как целое число без знака .Поэтому логическое смещение 16 приводит к 0x0000FFFF, как и ожидалось.

0 голосов
/ 21 сентября 2018

Когда вы говорите:

int x = 0xfffffffe;

Это устанавливает x в -2, потому что максимальное значение, которое может содержать int здесь, равно 0x7FFFFFFF, и оно оборачивается во время преобразования.Когда вы сдвигаете бит по отрицательному числу, оно становится странным .

Если вы измените эти значения на unsigned int, все получится.

#include <stdio.h>
int main(){
  unsigned int x = 0xfffffffe;
  unsigned int a = x >> 16;
  unsigned int b = 0xfffffffe >> 16;
  printf("%X\n%X\n", a, b);
  return 0;
}
...