Сдвиг влево с отрицательным счетом сдвига - PullRequest
60 голосов
/ 09 февраля 2011

Что именно здесь происходит?

a << -5

Очевидно, что это не вправо сдвиг. Но книга, которую я читаю, гласит:

На одной машине это выражение фактически выполняет сдвиг влево на 27 бит

Мой вопрос; Зачем? Что вызывает сдвиг влево на 27 бит? И что именно происходит при переключении с отрицательным счетом сдвига? Спасибо.

Ответы [ 5 ]

71 голосов
/ 09 февраля 2011

Отрицательные целые числа в правой части - неопределенное поведение в языке C.

ISO 9899: 2011 6.5.7 Операции побитового сдвига:

Целочисленные продвижения выполняются для каждого из операндов. Тип результата - тип повышенного левого операнда. Если значение правого операнда отрицательное или больше или равно ширине повышенного левого операнда, поведение не определено .

16 голосов
/ 09 февраля 2011

Как уже ответили другие участники, это вызывает неопределенное поведение. Здесь я хотел бы упомянуть, что вы цитируете книгу («На одной машине»), кажется, частично. Это не обобщает поведение. Книга также могла бы объяснить, что поведение не определено согласно стандарту. Кстати, я только что прочитал «Новый стандарт С - комментарий по экономике и культуре» и нашел это утверждение:

Инструкция Intel Pentium SAL (генерируется как gcc, так и Microsoft C ++ для оценки левых сдвигов) использует только нижние пять битов смены сумма

Это очень хорошо объясняет, почему сдвиг влево на -5 может привести к сдвигу влево на 27 (для представления отрицательных чисел в дополнение к 2)

11 голосов
/ 09 февраля 2011

Поведение не определено.

В 5-битной двоичной арифметике двоичное дополнение -5 имеет такое же двоичное представление, что и беззнаковое +27, что, вероятно, объясняет эту конкретную платформу.

1 голос
/ 16 августа 2016
int main()
{
    unsigned int a = 1;
    printf("%u\n",a<<(-1));
    return 0;
}

Вывод 2147483648.

Вот мое предположение и подтверждение: (просто предположение!)

1. Правый операнд "<<" должен иметь тип unsigned int, </strong>

Итак, во-первых, (int) «-1» будет приведено к (unsigned int) «-1». Потому что тип int является представлением с двумя дополнениями, результат будет 2 ^ 32-1 (без знака int)

2.В связи с тем, что число 2 ^ 32-1 больше, чем цифра максимального смещения, 2 ^ 32 - 1 будет мод 32, что равно 27

Я также пытался некоторые другие числовые номера правых операндов, и результаты ручного вычисления с предполагаемыми правилами будут такими же, как и у моего продукта в IDE.

Я пытаюсь найти некоторые подтверждающие официальные документы, ведьма может проверить, правильно ли мое предположение или нет. Может быть, вы можете сказать мне.

1 голос
/ 09 февраля 2011

Если значение, которое вы сдвигаете, является 32-битной переменной, сдвиг -5 идет в «цикле» и сдвигает 27 вперед. Сдвиг может происходить только «без знака».

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