По какой причине языки высокого уровня, такие как C # / Java, маскируют операнд счетчика битовых сдвигов? - PullRequest
16 голосов
/ 22 февраля 2010

Это скорее дизайн языка, нежели вопрос программирования.

Ниже приводится выдержка из JLS 15.19 Операторы сдвига :

Если повышенный тип левого операнда равен int, только пять младших битов правого операнда используются в качестве расстояния сдвига.

Если повышенный тип левого операнда равен long, то только шесть младших битов правого операнда используются в качестве расстояния сдвига.

Это поведение также указано в C # , и хотя я не уверен, что оно входит в официальную спецификацию для Javascript (если есть), оно также верно, по крайней мере, на основе моего собственного теста.

Следствием этого является следующее:

(1 << 32) == 1

Я понимаю, что эта спецификация, вероятно, "вдохновлена" тем фактом, что базовое оборудование берет только 5 битов для операнда подсчета при сдвиге 32-битных значений (и 6 битов для 64-битных), и я могу понять такое поведение указанный на уровне JVM, например, но почему языки высокого уровня, такие как C # и Java, сохраняют это довольно низкое поведение? Разве они не должны обеспечивать более абстрактное представление помимо аппаратной реализации и вести себя более интуитивно? (Еще лучше, если они могут принять отрицательный счет, чтобы означать сдвиг в ДРУГОМ направлении!)

Ответы [ 3 ]

8 голосов
/ 22 февраля 2010

Java и C # не являются полностью «высокоуровневыми». Они изо всех сил стараются быть такими, чтобы их можно было скомпилировать в эффективный код, чтобы проявить себя в микро-бенчмарках. Вот почему они имеют «типы значений», такие как int, вместо того, чтобы иметь в качестве целочисленного типа по умолчанию истинные целые числа, которые были бы объектами сами по себе и не ограничивались фиксированным диапазоном.

Следовательно, они имитируют то, что делает оборудование. Они немного его урезают, потому что они требуют маскирования, тогда как С это только позволяет. Тем не менее, Java и C # являются языками среднего уровня.

5 голосов
/ 22 февраля 2010

C # и Java определяют сдвиг как использование только младших битов счетчика сдвигов, поскольку это то, что делают и инструкции сдвига sparc и x86. Java изначально была реализована Sun на процессорах sparc, а C # - Microsoft на x86.

В отличие от этого, C / C ++ оставляют как неопределенное поведение инструкций сдвига, если счетчик сдвига не находится в диапазоне 0..31 (для 32-битного целого), допуская любое поведение. Это потому, что когда C был впервые реализован, различные ручные программы обрабатывали их по-разному. Например, на VAX смещение на отрицательную величину смещает другое направление. Так что с C компилятор может просто использовать команду аппаратного переключения и делать все, что он делает.

5 голосов
/ 22 февраля 2010

Поскольку в большинстве сред программирования целое число составляет всего 32 бита. Таким образом, 5 бит (что достаточно для выражения 32 значений) уже достаточно для сдвига целого числа. Аналогичное рассуждение существует для 64-битной длины: 6 бит - это все, что вам нужно для полного смещения всего значения.

Я могу понять часть путаницы: если ваш правый операнд является результатом вычисления, значение которого превышает 32, вы можете ожидать, что он просто сдвинет все биты, а не применит маску. 1003 *

...