¿Por qué byte + byte = int?

Resuelto Robert Cartaino asked hace 15 años • 0 respuestas

Mirando este código C#:

byte x = 1;
byte y = 2;
byte z = x + y; // ERROR: Cannot implicitly convert type 'int' to 'byte'

El resultado de cualquier cálculo realizado en byte(o short) tipos se convierte implícitamente en un número entero. La solución es convertir explícitamente el resultado a un byte:

byte z = (byte)(x + y); // this works

Lo que me pregunto es ¿por qué? ¿Es arquitectónico? ¿Filosófico?

Tenemos:

  • int+ int=int
  • long+ long=long
  • float+ float=float
  • double+ double=double

Entonces por qué no:

  • byte+ byte=byte
  • short+ short= short?

Un poco de historia: estoy realizando una larga lista de cálculos con "números pequeños" (es decir, <8) y almacenando los resultados intermedios en una matriz grande. Usar una matriz de bytes (en lugar de una matriz int) es más rápido (debido a los aciertos de caché). Pero la extensa difusión de bytes repartida por el código lo hace mucho más ilegible.

Robert Cartaino avatar Jun 03 '09 02:06 Robert Cartaino
Aceptado

La tercera línea de tu fragmento de código:

byte z = x + y;

en realidad significa

byte z = (int) x + (int) y;

Por lo tanto, no existe una operación + en bytes, los bytes se convierten primero en números enteros y el resultado de la suma de dos números enteros es un número entero (32 bits).

azheglov avatar Jun 02 '2009 20:06 azheglov

En términos de "por qué sucede", es porque no hay operadores definidos por C# para aritmética con byte, sbyte, short o ushort, tal como otros han dicho. Esta respuesta trata sobre por qué esos operadores no están definidos.

Creo que es básicamente por el rendimiento. Los procesadores tienen operaciones nativas para hacer aritmética con 32 bits muy rápidamente. Se podría realizar la conversión del resultado a un byte automáticamente , pero daría lugar a penalizaciones de rendimiento en el caso de que en realidad no desee ese comportamiento.

Creo que esto se menciona en uno de los estándares de C# comentados. Mirando...

EDITAR: Es molesto que ahora haya revisado la especificación ECMA C# 2 anotada, la especificación MS C# 3 anotada y la especificación CLI de anotación, y ninguna de ellas menciona esto hasta donde puedo ver. Estoy seguro de haber visto el motivo indicado anteriormente, pero estoy desconcertado si sé dónde. Disculpas, fans de referencia :(

Jon Skeet avatar Jun 02 '2009 20:06 Jon Skeet

Del artículo ¿Por qué las operaciones con "byte" dan como resultado "int"? en el blog de Raymond Chen, The Old New Thing:

Supongamos que viviéramos en un mundo de fantasía donde las operaciones con "byte" daban como resultado "byte".

byte b = 32;
byte c = 240;
int i = b + c; // what is i?

¡En este mundo de fantasía, el valor de i sería 16! ¿Por qué? Debido a que los dos operandos del operador + son ambos bytes, la suma "b+c" se calcula como un byte, lo que da como resultado 16 debido al desbordamiento de enteros. (Y, como señalé anteriormente, el desbordamiento de enteros es el nuevo vector de ataque a la seguridad ).

Raymond defiende, esencialmente, el enfoque que adoptaron originalmente C y C++. En los comentarios, defiende el hecho de que C# adopta el mismo enfoque, basándose en la compatibilidad del lenguaje con versiones anteriores.

Michael Petrotta avatar Jun 02 '2009 20:06 Michael Petrotta

C#

ECMA-334 establece que la suma solo se define como legal en int+int, uint+uint, long+long y ulong+ulong (ECMA-334 14.7.4). Como tales, estas son las operaciones candidatas a considerar con respecto a 14.4.2. Debido a que hay conversiones implícitas de byte a int, uint, long y ulong, todos los miembros de la función de suma son miembros de función aplicables según 14.4.2.1. Tenemos que encontrar la mejor conversión implícita según las reglas de 14.4.2.3:

Convertir(C1) a int(T1) es mejor que convertir(C2) a uint(T2) o ulong(T2) porque:

  • Si T1 es int y T2 es uint o ulong, C1 es la mejor conversión.

Convertir(C1) a int(T1) es mejor que convertir(C2) a long(T2) porque hay una conversión implícita de int a long:

  • Si existe una conversión implícita de T1 a T2 y no existe ninguna conversión implícita de T2 a T1, C1 es la mejor conversión.

Por lo tanto, se utiliza la función int+int, que devuelve un int.

Lo cual es un largo camino para decir que está enterrado muy profundamente en la especificación de C#.

CLI

La CLI opera solo en 6 tipos (int32, native int, int64, F, O y &). (ECMA-335 partición 3 sección 1.5)

El byte (int8) no es uno de esos tipos y se convierte automáticamente en int32 antes de la adición. (ECMA-335 partición 3 sección 1.6)

Alun Harford avatar Jun 02 '2009 23:06 Alun Harford