Como se explica en breve C # (pero también para otros compiladores de lenguajes, como Java)
Hay una conversión implícita predefinida de short a int, long, float, double o decimal.
No puede convertir implícitamente tipos numéricos no literales de tamaño de almacenamiento más grande en cortos (consulte la Tabla de tipos integrales para conocer los tamaños de almacenamiento de los tipos integrales). Considere, por ejemplo, las siguientes dos variables cortas xey:
short x = 5, y = 12;
La siguiente declaración de asignación producirá un error de compilación, porque la expresión aritmética en el lado derecho del operador de asignación se evalúa como int por defecto.
short z = x + y;
Para solucionar este problema, use un yeso:
short z = (short)(x + y);
Sin embargo, es posible utilizar las siguientes declaraciones, donde la variable de destino tiene el mismo tamaño de almacenamiento o un tamaño de almacenamiento mayor:
int m = x + y;
long n = x + y;
Una buena pregunta de seguimiento es:
"¿Por qué la expresión aritmética en el lado derecho del operador de asignación se evalúa como int por defecto"?
Una primera respuesta se puede encontrar en:
Clasificación y verificación formal de plegado constante de enteros
La especificación del lenguaje Java define exactamente cómo se representan los números enteros y cómo se evaluarán las expresiones aritméticas de enteros . Esta es una propiedad importante de Java, ya que este lenguaje de programación ha sido diseñado para ser utilizado en aplicaciones distribuidas en Internet. Se requiere un programa Java para producir el mismo resultado independientemente de la máquina de destino que lo ejecute .
Por el contrario, C (y la mayoría de los lenguajes de programación imperativos y orientados a objetos ampliamente utilizados) es más descuidado y deja abiertas muchas características importantes. La intención detrás de esta especificación de lenguaje inexacta es clara. Se supone que los mismos programas en C se ejecutan en una arquitectura de 16 bits, 32 bits o incluso 64 bits al crear instancias de la aritmética entera de los programas fuente con las operaciones aritméticas integradas en el procesador de destino. Esto conduce a un código mucho más eficiente porque puede usar las operaciones de la máquina disponibles directamente. Siempre que los cálculos de números enteros se ocupen únicamente de que los números sean "suficientemente pequeños", no surgirán inconsistencias.
En este sentido, la aritmética de enteros en C es un marcador de posición que no está definido exactamente por la especificación del lenguaje de programación, sino que solo se instancia completamente al determinar la máquina de destino.
Java define con precisión cómo se representan los enteros y cómo se calcula la aritmética de enteros.
Java Integers
--------------------------
Signed | Unsigned
--------------------------
long (64-bit) |
int (32-bit) |
short (16-bit) | char (16-bit)
byte (8-bit) |
Char es el único tipo de entero sin signo. Sus valores representan caracteres Unicode, de \u0000
a \uffff
, es decir, de 0 a 2 16 −1.
Si un operador entero tiene un operando de tipo long, entonces el otro operando también se convierte a tipo long. De lo contrario, la operación se realiza en operandos de tipo int, si es necesario, los operandos más cortos se convierten en int . Las reglas de conversión se especifican exactamente.
[De Electronic Notes in Theoretical Computer Science 82 No. 2 (2003)
Blesner-Blech-COCV 2003: Sabine GLESNER , Jan Olaf BLECH,
Fakultät für Informatik,
Universität Karlsruhe
Karlsruhe, Alemania]
T a, b; a += b
es equivalente aT a, b; a = (T) (a + b)
: observe la conversión agregada por el compilador.EDITAR: Bien, ahora sabemos que es Java ...
La sección 4.2.2 de la especificación del lenguaje Java establece:
En otras palabras, es como C #: el operador de suma (cuando se aplica a tipos integrales) solo da como resultado
int
olong
, por lo que necesita convertir para asignar a unashort
variable.Respuesta original (C #)
En C # (no ha especificado el idioma, supongo), los únicos operadores de suma en tipos primitivos son:
int operator +(int x, int y); uint operator +(uint x, uint y); long operator +(long x, long y); ulong operator +(ulong x, ulong y); float operator +(float x, float y); double operator +(double x, double y);
Estos se encuentran en la especificación C # 3.0, sección 7.7.4. Además, se define la suma decimal:
(La suma de enumeración, la concatenación de cadenas y la combinación de delegados también se definen allí).
Como puede ver, no hay
short operator +(short x, short y)
operador, por lo que ambos operandos se convierten implícitamente a int y se usa la forma int. Eso significa que el resultado es una expresión de tipo "int", de ahí la necesidad de emitir.fuente
En C # y Java, la expresión aritmática del lado derecho de la asignación se evalúa como int de forma predeterminada. Es por eso que necesita volver a un short, porque no hay una conversión implícita de int a short, por razones obvias.
fuente
Dado que la pregunta "por qué int por defecto" no ha sido respondida ...
Primero, "predeterminado" no es realmente el término correcto (aunque lo suficientemente cercano). Como señaló VonC, una expresión compuesta de ints y longs tendrá un resultado largo. Y una operación que consta de entradas / registros y dobles tendrá un resultado doble. El compilador promueve los términos de una expresión a cualquier tipo que proporcione un mayor rango y / o precisión en el resultado (se supone que los tipos de punto flotante tienen mayor rango y precisión que la integral, aunque se pierde precisión al convertir largos largos en dobles).
Una advertencia es que esta promoción solo se aplica a los términos que la necesitan. Entonces, en el siguiente ejemplo, la subexpresión 5/4 usa solo valores integrales y se realiza usando matemáticas enteras, aunque la expresión general involucra un doble. El resultado no es el que cabría esperar ...
(5/4) * 1000.0
Bien, entonces, ¿por qué byte y short se promueven a int? Sin ninguna referencia que me respalde, se debe a la practicidad: hay un número limitado de códigos de bytes.
"Bytecode", como su nombre lo indica, utiliza un solo byte para especificar una operación. Por ejemplo iadd , que suma dos ints. Actualmente, se definen 205 códigos de operación y las matemáticas de números enteros toman 18 para cada tipo (es decir, 36 en total entre números enteros y largos), sin contar los operadores de conversión.
Si es corto, y cada byte tiene su propio conjunto de códigos de operación, estaría en 241, lo que limita la capacidad de expansión de la JVM. Como dije, no hay referencias que me respalden en esto, pero sospecho que Gosling et al dijeron "¿con qué frecuencia la gente usa realmente pantalones cortos?" Por otro lado, la promoción de bytes a int conduce a este efecto no tan maravilloso (la respuesta esperada es 96, la real es -16):
byte x = (byte)0xC0; System.out.println(x >> 2);
fuente
>>
lanza aint
?? El efecto, sin embargo, es lo que en Z80 se llamaSRA
(desplazamiento aritmético a la derecha), que desplaza bits de un byte al lugar 1 de la derecha, perdiendo el que está más a la derecha y duplicando el que está más a la izquierda (dividiendo así un byte con signo por 2), en lugar deSRL
(desplazamiento lógico a la derecha), que deja un bit cero a la izquierda (lo mismo que dividir un byte sin signo por 2), que es en lo que se basa la "respuesta esperada".Qué idioma estás usando?
Muchos lenguajes basados en C tienen la regla de que cualquier expresión matemática se realiza en tamaño int o mayor. Debido a esto, una vez que agrega dos cortos, el resultado es de tipo int. Esto provoca la necesidad de un yeso.
fuente
Java siempre utiliza al menos valores de 32 bits para los cálculos. Esto se debe a la arquitectura de 32 bits que era común en 1995 cuando se introdujo Java. El tamaño del registro en la CPU era de 32 bits y la unidad aritmética lógica aceptaba 2 números de la longitud de un registro de la CPU. Entonces, los cpus se optimizaron para tales valores.
Esta es la razón por la que todos los tipos de datos que admiten operaciones aritméticas y tienen menos de 32 bits se convierten a int (32 bits) tan pronto como los usa para los cálculos.
Entonces, en resumen, se debió principalmente a problemas de rendimiento y hoy en día se mantiene por compatibilidad.
fuente
En java, cada expresión numérica como:
anyPrimitive zas = 1; anyPrimitive bar = 3; ?? x = zas + bar
x siempre resultará ser al menos un int, o un long si uno de los elementos de adición fue un long.
Pero hay algunas peculiaridades difíciles
byte a = 1; // 1 is an int, but it won't compile if you use a variable a += 2; // the shortcut works even when 2 is an int a++; // the post and pre increment operator work
fuente
AFAIS, nadie menciona el
final
uso de eso. Si modifica su último ejemplo y define las variables ayb comofinal
variables, entonces el compilador tiene la seguridad de que su suma, valor 5, puede asignarse a una variable de tipobyte
, sin pérdida de precisión. En este caso, el compilador es bueno para asignar la suma de ayb a c. Aquí está el código modificado:final byte a = 2; final byte b = 3; byte c = a + b;
fuente
final byte a = (byte) (new Random().nextInt(4));
yIncompatible types
asoma de nuevo su fea cabeza. No es solo finalidad, es poder compilarlo a un valor que se ajuste al tipo.final
compilador asegura , y puede que no sea suficiente. Si tomamos su ejemplo palabra por palabra, todo está bien. Pero intente reemplazarlob = 3
conb = (byte)(new Random().nextInt(4))
. y los tipos incompatibles están de vuelta y a + b necesita conversión nuevamente. Es posible que desee agregar eso a su respuesta.Cualquier tipo de datos que sea menor que "int" (excepto booleano) se convierte implícitamente en "int".
En tu caso:
short a = 2; short b = 3; short c = a + b;
El resultado de (a + b) se convierte implícitamente en un int. Y ahora lo estás asignando a "corto". De modo que obtienes el error.
short, byte, char - para todos estos obtendremos el mismo error.
fuente
Me gustaría agregar algo que no se ha señalado. Java no tiene en cuenta los valores que le ha dado a las variables (2 y 3) en ...
corto a = 2; corto b = 3; corto c = a + b;
Por lo que Java sabe, podrías hacer esto ...
corto a = 32767; corto b = 32767; corto c = a + b;
Lo cual estaría fuera del rango de short, automáticamente pone el resultado en un int porque es "posible" que el resultado sea más que un short pero no más que un int. Se eligió Int como "predeterminado" porque, básicamente, la mayoría de las personas no codificarán valores por encima de 2,147,483,647 o por debajo de -2,147,483,648
fuente