c# - operadores - programacion en ca bajo nivel
C#XOR en variables de dos bytes no se compilará sin una conversión (8)
¿Por qué los dos bytes se deben convertir a ints para hacer el XOR?
Si desea profundizar en él, 12.1.2 de la CLI Spec (Partition I) describe el hecho de que, en la pila de evaluación, solo puede existir int o long. Todos los tipos de integrales más cortos deben expandirse durante la evaluación.
Desafortunadamente, no puedo encontrar un enlace adecuado directamente a la especificación de la CLI: tengo una copia local como PDF, pero no puedo recordar de dónde la obtuve.
Esta pregunta ya tiene una respuesta aquí:
- byte + byte = int ... ¿por qué? 15 respuestas
¿Por qué lo siguiente genera un error de tiempo de compilación: ''No se puede convertir implícitamente el tipo'' int ''a'' byte '':
byte a = 25;
byte b = 60;
byte c = a ^ b;
Esto tendría sentido si estuviera usando un operador aritménico porque el resultado de a + b podría ser mayor que el que se puede almacenar en un solo byte.
Sin embargo, aplicar esto al operador XOR no tiene sentido. XOR aquí es una operación bitwise que nunca puede desbordar un byte.
utilizando un reparto alrededor de los dos operandos funciona:
byte c = (byte)(a ^ b);
El programador de semidios de Microsoft tiene una respuesta: http://blogs.msdn.com/oldnewthing/archive/2004/03/10/87247.aspx
Y tal vez sea más sobre el diseño del compilador. Hacen que el compilador sea más simple al generalizar el proceso de compilación, no tiene que ver al operador de los operandos, por lo que agrupó las operaciones bitwise en la misma categoría que los operadores aritméticos. Por lo tanto, sometido a ampliación de tipo.
Esto tiene más que ver con las reglas que rodean la conversión implícita y explícita en la especificación de la CLI. Un entero (int = System.Int32 = 4 bytes) es más ancho que un byte (¡1 byte, obviamente!). Por lo tanto, cualquier lanzamiento de int a byte es potencialmente un lanzamiento de estrechamiento. Por lo tanto, el compilador quiere que hagas esto explícito.
FWIW byte a = 25; byte b = 60; a = a ^ b; No funciona. Sin embargo, el byte a = 25; byte b = 60; a ^ = b; funciona.
No puedo darte la razón, pero puedo decir por qué el compilador tiene ese comportamiento desde el punto de vista de las reglas que debe seguir el compilador (lo que podría no ser lo que realmente te interesa saber).
A partir de una copia antigua de la especificación de C # (probablemente debería descargar una versión más reciente), énfasis agregado:
14.2.6.2 Promociones numéricas binarias Esta cláusula es informativa.
La promoción numérica binaria se produce para los operandos de los predefinidos
+
,? ,*
,/
,%
,&
,|
,^
,==
!=
,>
,<
,>=
y<=
operadores binarios. La promoción numérica binaria convierte implícitamente ambos operandos a un tipo común que, en el caso de los operadores no relacionales, también se convierte en el tipo de resultado de la operación. La promoción numérica binaria consiste en aplicar las siguientes reglas, en el orden en que aparecen aquí:
- Si cualquiera de los operandos es de tipo decimal, el otro se convierte al tipo decimal, o se produce un error en tiempo de compilación si el otro operando es de tipo float o double.
- De lo contrario, si cualquiera de los operandos es de tipo doble, el otro operando se convierte en tipo doble.
- De lo contrario, si cualquiera de los operandos es de tipo float, el otro operando se convierte en tipo float.
- De lo contrario, si cualquiera de los operandos es de tipo ulong, el otro se convierte al tipo ulong, o se produce un error en tiempo de compilación si el otro operando es de tipo sbyte, short, int o long.
- De lo contrario, si cualquiera de los operandos es de tipo largo, el otro operando se convierte en tipo long.
- De lo contrario, si cualquiera de los operandos es de tipo uint y el otro es de tipo sbyte, short o int, ambos operandos se convierten en tipo long.
- De lo contrario, si cualquiera de los operandos es de tipo uint, el otro operando se convierte al tipo uint.
- De lo contrario, ambos operandos se convierten al tipo int .
Entonces, básicamente los operandos más pequeños que un int
se convertirán a int
para estos operadores (y el resultado será un int
para las operaciones no relacionales).
Dije que no podía darte una razón; sin embargo, haré una conjetura a una; creo que los diseñadores de C # querían asegurarse de que las operaciones que podrían perder información si se restringieran necesitarían que la operación de estrechamiento se hiciera explícita por el programador en forma de un molde. Por ejemplo:
byte a = 200;
byte b = 100;
byte c = a + b; // value would be truncated
Si bien este tipo de truncamiento no sucedería al realizar una operación xor entre operandos de dos bytes, creo que los diseñadores de lenguaje probablemente no quisieran tener un conjunto de reglas más complejo donde algunas operaciones necesitarían conversiones explícitas y otras no.
Solo una pequeña nota: la cita anterior es "informativa" no "normativa", pero cubre todos los casos de una forma fácil de leer. Hablando estrictamente (en un sentido normativo), la razón por la que el operador ^
comporta de esta manera es porque la sobrecarga más cercana para ese operador cuando se trata de operandos de byte
es (desde 14.10.1 "Operadores lógicos enteros"):
int operator ^(int x, int y);
Por lo tanto, como lo explica el texto informativo, los operandos se promueven a int
y se produce un resultado int
.
Parece ser porque en las especificaciones de lenguaje C #, se define para enteros y largos http://msdn.microsoft.com/en-us/library/aa691307%28v=VS.71%29.aspx
Entonces, lo que realmente sucede es que el compilador lanza operandos de bytes a int implícitamente porque no hay pérdida de datos de esa manera. Pero el resultado (que es int) no puede ser desviado sin pérdida de datos (implícitamente). Por lo tanto, debe decirle al compilador explícitamente que sabe lo que está haciendo.
Pensé que recordaba una pregunta popular sobre esto.
Supongo que es porque el operador XOR está definido para booleanos y enteros.
Y una conversión del resultado del resultado entero a un byte es una conversión que pierde información; Por lo tanto, necesita un reparto explícito (asentimiento del programador).