2010-02-22 9 views
14

Esto es más un diseño de lenguaje que una cuestión de programación.¿Cuál es la razón por la que los lenguajes de alto nivel como C#/Java enmascaran el operando de recuento de desplazamiento de bit?

El siguiente es un extracto de JLS 15.19 Shift Operators:

Si el tipo promovido del operando de la izquierda es int, sólo se utilizan los cinco bits de menor orden del operando de la derecha como de la distancia de desplazamiento .

Si el tipo promocionado del operando de la izquierda es long, solo se utilizan los seis bits de menor orden del operando de la derecha como distancia de desplazamiento.

Este comportamiento es también specified in C#, y aunque no estoy seguro de si es en la especificación oficial de Javascript (si hay uno), también es cierto basado en mi propia prueba por lo menos.

La consecuencia es que se cumple lo siguiente:

(1 << 32) == 1 

entiendo que esta especificación es, probablemente, "inspirado" por el hecho de que el hardware subyacente sólo toma 5 bits para el operando recuento cuando se pasa de 32 bits valores (y 6 bits para 64 bits), y puedo entender dicho comportamiento especificado en el nivel de JVM, por ejemplo, pero ¿por qué los lenguajes de alto nivel como C# y Java conservan este comportamiento de bajo nivel? ¿No deberían proporcionar una visión más abstracta más allá de la implementación del hardware y comportarse de manera más intuitiva? (Incluso mejor si se puede hacer un conteo negativo en el sentido de cambiar en la otra dirección!)

Respuesta

8

Java y C# no son completamente "de alto nivel". Intentan realmente serlo para que puedan compilarse en un código eficiente, para brillar en micro-puntos de referencia. Es por eso que tienen los "tipos de valor" como int en lugar de tener, como tipo de entero por defecto, enteros verdaderos, que serían objetos por derecho propio, y no están limitados a un rango fijo.

Por lo tanto, imitan lo que hace el hardware. Lo recortan un poco, ya que enmascara el mandato, mientras que C solo lo permite. Aún así, Java y C# son idiomas de "nivel medio".

+0

La determinación de si un lenguaje es de alto nivel o no es muy subjetivo, lo entiendo. Sin embargo, creo que la mayoría de las personas clasificaría Java y C# como "alto", al menos para los lenguajes que no usan scripts. – polygenelubricants

+0

Absolutamente. Pero Java y C# aún conservan características de bajo nivel, por el bien de la eficiencia (o al menos _eficacia percibida_). El tipo 'int' de 32 bits y el enmascaramiento de recuento de turnos son tales características. Otros idiomas, como Scheme, son de "nivel superior" en esa materia. –

+0

http://therighttool.hammerprinciple.com/statements/this-is-a-high-level-language – starblue

5

Debido a que en la mayoría de entornos de programación es un entero sólo 32 bits. Entonces, 5 bits (que es suficiente para expresar 32 valores) ya son suficientes para cambiar todo el entero. Existe un razonamiento similar para una longitud de 64 bits: 6 bits es todo lo que necesita para cambiar completamente el valor completo.

Entiendo parte de la confusión: si su operando de la mano derecha es el resultado de un cálculo que termina con un valor mayor a 32, puede esperar que simplemente cambie todos los bits en lugar de aplicar una máscara.

+0

Entiendo por qué el cambio efectivo de un valor de 32 bits solo necesita 5 bits como máximo, y cualquier cosa más allá borra todo el registro, y como usuario del lenguaje, a veces eso es exactamente lo que quiero. Como dije, la pregunta no es por qué los parámetros se eligen como tales, sino más bien por qué se retiene algo de tan bajo nivel en el lenguaje de alto nivel. – polygenelubricants

+0

'si su operando de la mano derecha es el resultado de un cálculo que termina con un valor mayor a 32' ... 5 bits pueden almacenar valores de 0 a 31, por lo que simplemente no es posible desplazarse en 32 bits, ni lo haría así que sea útil, ya que un simple 'xor reg, reg' lograría el mismo efecto. –

5

C# y Java definen como el cambio utilizando sólo los bits de orden del turno contará como eso es lo que ambas instrucciones SPARC y x86 de cambio hacen. Java fue implementado originalmente por Sun en procesadores sparc, y C# por Microsoft en x86.

En contraste, C/C++ deja como indefinido el comportamiento de las instrucciones de desplazamiento si el recuento de cambios no está en el rango 0..31 (para un int de 32 bits), lo que permite cualquier comportamiento. Esto se debe a que cuando C se implementó por primera vez, los diferentes handwares los manejaban de manera diferente. Por ejemplo, en un VAX, el cambio por una cantidad negativa cambia la otra dirección. Entonces, con C, el compilador puede usar la instrucción de cambio de hardware y hacer lo que haga.

Cuestiones relacionadas