Какова причина высокоуровневые языки как маска C#/Java операнд количества сдвига разряда?

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

Следующее является выборкой от операторов сдвига JLS 15.19:

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

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

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

Последствие - то, что следующее верно:

(1 << 32) == 1

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

16
задан pelumi 2 October 2015 в 10:53
поделиться

3 ответа

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

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

8
ответ дан 30 November 2019 в 22:31
поделиться

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

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

5
ответ дан 30 November 2019 в 22:31
поделиться

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

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

5
ответ дан 30 November 2019 в 22:31
поделиться