C # bit shift: это поведение в спецификации, ошибка или случайность? - PullRequest
5 голосов
/ 24 февраля 2010

Я работал с операторами сдвига битов (см. Мой вопрос Битовое равенство массивов ), и пользователь SO указал на ошибку в моем вычислении операнда сдвига - я вычислял диапазон [1, 32] вместо [0,31] для цел. (Ура для SO сообщества!)

При устранении проблемы я с удивлением обнаружил следующее поведение:

-1 << 32 == -1

На самом деле может показаться, что n << s компилируется (или интерпретируется CLR - я не проверял IL) как n << s % bs(n), где bs (n) = размер, в битах, n.

Я бы ожидал:

-1 << 32 == 0

Казалось бы, компилятор понимает, что вы смещаетесь за пределы цели и исправляете свою ошибку.

Это чисто академический вопрос, но кто-нибудь знает, определено ли это в спецификации (я не смог найти ничего в 7.8 Операции сдвига ), просто случайный факт неопределенного поведения или есть случай, когда это может привести к ошибке?

1 Ответ

9 голосов
/ 24 февраля 2010

Я считаю, что соответствующая часть спецификации находится здесь:

Для предопределенных операторов число сдвигаемых битов вычисляется следующим образом:

  • Когда тип x имеет тип int или uint, число сдвигов определяется младшие пять битов. Другими словами, подсчет сдвига вычисляется из подсчета & 0x1F.

  • Когда тип x длинный или ulong, число сдвигов определяется младшие шесть битов. Другими словами, подсчет сдвига вычисляется из подсчета & 0x3F.

Если полученный счетчик сдвига равен нулю, операторы сдвига просто возвращают значение из х.

Значение 32 равно 0x20. Выражение 0x20 & 0x1F оценивается как 0. Следовательно, отсчет сдвига равен нулю, и сдвиг не выполняется; выражение -1 << 32 (или любое x << 32) просто возвращает исходное значение.

...