O-ing bytes en C # da int [duplicado]
-
06-07-2019 - |
Pregunta
Esta pregunta ya tiene una respuesta aquí:
- Desplazamiento de bit izquierdo 255 (como byte) 7 respuestas
Tengo este código.
byte dup = 0;
Encoding.ASCII.GetString(new byte[] { (0x80 | dup) });
Cuando intento compilar obtengo:
No se puede convertir implícitamente el tipo 'int' a 'byte'. Una conversión explícita existe (¿te falta un elenco?)
¿Por qué sucede esto? No debería | dos bytes dan un byte? Los dos trabajos siguientes aseguran que cada elemento sea un byte.
Encoding.ASCII.GetString(new byte[] { (dup) });
Encoding.ASCII.GetString(new byte[] { (0x80) });
Solución
Es así por diseño en C # y, de hecho, se remonta a C / C ++; este último también promueve operandos a int
, por lo general no se nota porque hay una conversión int -> char
implícito, mientras que no está en C #. Esto no solo se aplica a |
tampoco, sino a todos los operandos aritméticos y bit a bit, p. agregar dos byte
s también le dará un (byte)200 + (byte)100
. Citaré la parte relevante de la especificación aquí:
Se produce promoción numérica binaria para los operandos de los predefinidos +, & # 8211 ;, *, /,%, & amp ;, |, ^, ==,! =, > ;, < ;, > =, y < = operadores binarios . Binario la promoción numérica convierte implícitamente ambos operandos a un tipo común que, en caso de no relacional operadores, también se convierte en el resultado tipo de la operación. Numérico binario la promoción consiste en aplicar el siguiendo las reglas, en el orden en que aparece aquí:
Si cualquiera de los operandos es de escriba decimal, el otro operando es convertido a tipo decimal, o un se produce un error en tiempo de compilación si el otro el operando es de tipo flotante o doble.
De lo contrario, si cualquiera de los operandos es de escriba double, el otro operando es convertido a tipo doble.
De lo contrario, si cualquiera de los operandos es de tipo flotante, el otro operando se convierte a tipo flotador.
De lo contrario, si cualquiera de los operandos es de tipo ulong, el otro operando es convertido a tipo ulong, o un se produce un error en tiempo de compilación si el otro el operando es de tipo sbyte, short, int, o largo.
De lo contrario, si operando es de tipo largo, el otro el operando se convierte a tipo largo.
De lo contrario, si cualquiera de los operandos es de escriba uint y el otro operando es de escriba sbyte, short o int, ambos los operandos se convierten a tipo largo.
De lo contrario, si cualquiera de los operandos es de escriba uint, el otro operando es convertido a tipo uint.
De lo contrario, ambos operandos se convierten a tipo int.
No sé la razón exacta de esto, pero puedo pensar en uno. Especialmente para los operadores aritméticos, puede ser un poco sorprendente para las personas obtener 44
de repente igual a <=>, incluso si tiene algún sentido cuando uno considera cuidadosamente los tipos involucrados. Por otro lado, <=> generalmente se considera un tipo que es & Quot; suficientemente bueno & Quot; para la aritmética en la mayoría de los números típicos, por lo que al promover ambos argumentos a <=>, obtienes una especie de & "; simplemente funciona &"; comportamiento para los casos más comunes.
En cuanto a por qué esta lógica también se aplicó a los operadores bit a bit, me imagino que esto es principalmente por coherencia. Da como resultado una sola regla simple que es común para todos tipos binarios no booleanos.
Pero todo esto es principalmente adivinar. Eric Lippert probablemente sea el que pregunte sobre los motivos reales detrás de esta decisión para C # al menos (aunque sería un poco aburrido si la respuesta es simplemente & "; Así es como se hace en C / C ++ y Java, y es una regla lo suficientemente buena como es, así que no vimos ninguna razón para cambiarla ").
Otros consejos
El literal 0x80 tiene el tipo " int " ;, por lo que no está ordeando bytes.
Que puede pasarlo al byte [] solo funciona porque 0x80 (como literal) está dentro del rango del byte.
Editar : incluso si 0x80 se convierte a un byte, el código aún no se compilaría, ya que oring bytes aún dará int. Para que se compile, el resultado de o debe ser emitido: (byte)(0x80|dup)
byte dup = 0;
Encoding.ASCII.GetString(new byte[] { (byte)(0x80 | dup) });
El resultado de un bit a bit (|) en dos bytes es siempre un int.