OU-ing bytes em C # dá int [duplicado]
-
06-07-2019 - |
Pergunta
Esta questão já tem uma resposta aqui:
- Esquerda bit deslocando 255 (como um byte) 7 respostas
Eu tenho esse código.
byte dup = 0;
Encoding.ASCII.GetString(new byte[] { (0x80 | dup) });
Quando tento compilar recebo:
Não é possível converter implicitamente tipo 'int' para 'byte'. Uma conversão explícita existe (faltam um elenco?)
Por que isso acontece? não deve | dois bytes dar um byte? Ambos os seguintes trabalhos, garantindo que cada item é um byte.
Encoding.ASCII.GetString(new byte[] { (dup) });
Encoding.ASCII.GetString(new byte[] { (0x80) });
Solução
É dessa maneira por design em C #, e, de fato, remonta todo o caminho para C / C ++ - este último também promove operandos para int
, você só geralmente não percebe porque a conversão int -> char
há implícita, embora seja não em C #. Isto não se aplica apenas para |
qualquer um, mas a todos os operandos aritméticos e bit a bit - por exemplo, adicionando duas byte
s lhe dará uma int
também. Vou citar a parte relevante da especificação aqui:
Binary promoção numérico ocorre para operandos do predefinidos +, -, *, /,%, &, |, ^, ==, =,>, <,> =, e <= operadores binários!. Binário promoção numérico converte implicitamente ambos os operandos para um tipo comum que, no caso do não-relacional operadores, também se torna o resultado tipo de operação. numérico binário promoção consiste em aplicar a seguindo as regras, na ordem em que apareça aqui:
Se qualquer operando é do tipo decimal, o outro operando é convertido para o tipo decimal, ou um erro de compilação ocorre se o outro operando é do tipo float ou double.
Caso contrário, se o operando é de tipo duplo, o outro é operando convertido para o tipo duplo.
Caso contrário, se quer operando é do tipo flutuador, o outro operando é convertido no tipo float.
Caso contrário, se o operando é do tipo ulong, o outro operando é convertido para o tipo ulong, ou um erro de compilação ocorre se o outro operando é do tipo sbyte, short, int, ou longo prazo.
Caso contrário, se quer operando é do tipo de comprimento, a outra operando é convertido no tipo longa.
Caso contrário, se o operando é de tipo uint e o outro operando é de Tipo sbyte, short ou int, tanto operandos são convertidos para o tipo long.
Caso contrário, se o operando é de tipo uint, o outro operando é convertidos para o tipo uint.
Caso contrário, ambos os operandos são convertidos para o tipo int.
Eu não sei a razão exata para isso, mas eu posso pensar em um. Para os operadores aritméticos especialmente, pode ser um pouco surpreendente para as pessoas obterem (byte)200 + (byte)100
repente igual a 44
, mesmo que isso faz algum sentido quando se considera cuidadosamente os tipos envolvidos. Por outro lado, int
é geralmente considerado um tipo que é "bom o suficiente" para aritmética sobre a maioria dos números típicos, assim, promovendo ambos os argumentos para int
, você começa uma espécie de "simplesmente funciona" comportamento para a maioria dos casos comuns.
Quanto ao porquê esta lógica também foi aplicada a bit a bit operadores - Eu imagino que isso é assim na maior parte para a consistência. Isso resulta em uma única regra simples que é comum para todas tipos binários não-booleanas.
Mas tudo isso é principalmente adivinhando. Eric Lippert provavelmente seria o único a perguntar sobre os reais motivos por trás desta decisão para C #, pelo menos, (apesar de que seria um pouco chato se a resposta é simplesmente "é como ele é feito em C / C ++ e Java, e é uma boa o suficiente norma, tal como é, por isso, não viu nenhuma razão para mudá-lo ").
Outras dicas
O 0x80 literal tem a "int" tipo, para que não sejam oring bytes.
Que você pode passá-lo para o byte [] só funciona porque 0x80 (como um literal) está dentro do intervalo de byte.
Editar : Mesmo se 0x80 é convertido para um byte, o código ainda não compilar, desde ORING bytes vai ainda dar int. Para tê-lo compilar, o resultado da ou deve ser lançado: (byte)(0x80|dup)
byte dup = 0;
Encoding.ASCII.GetString(new byte[] { (byte)(0x80 | dup) });
O resultado de uma operação OR (|). Em dois bytes é sempre um int