Eu preciso converter um int
para uma byte[]
maneira de fazê-lo é usar BitConverter.GetBytes()
. Mas não tenho certeza se isso corresponde à seguinte especificação:
Um número inteiro assinado por XDR é um dado de 32 bits que codifica um número inteiro no intervalo [-2147483648,2147483647]. O número inteiro é representado na notação de complemento de dois. Os bytes mais e menos significativos são 0 e 3, respectivamente. Os números inteiros são declarados da seguinte maneira:
Fonte: RFC1014 3.2
Como eu poderia fazer uma transformação de byte int que satisfizesse a especificação acima?
c#
.net
bit-manipulation
nfs
Peter
fonte
fonte
Respostas:
O RFC está apenas tentando dizer que um número inteiro assinado é um número inteiro normal de 4 bytes com bytes ordenados de maneira big-endian.
Agora, você provavelmente está trabalhando em uma máquina little-endian e
BitConverter.GetBytes()
lhe dará obyte[]
contrário. Então você pode tentar:Para que o código seja mais portátil, você pode fazer o seguinte:
fonte
byte[] result = intBytes;
?intBytes
já não é o array que você deseja?result
é redundante neste código. No entanto, senti que era mais pedagógico mostrar explicitamente ao leitor qual era o resultado do que supor que eles possam descobrir que o resultado está contido em alguma variável denominadaintBytes
. Além disso, fazer a atribuição é barato, pois não copia a memória nem aloca nova memória, apenas adiciona um novo nome à matriz já alocada. Então, por que não fazer isso?Aqui está outra maneira de fazer isso: como todos sabemos 1x byte = 8x bits e também um número inteiro "regular" (int32) contém 32 bits (4 bytes). Podemos usar o operador >> para mudar os bits para a direita (o operador >> não altera o valor.)
fonte
& 0xFF
bits são desnecessários.unchecked
bloco. Atualmente, ele só funciona se a verificação de estouro inteiro estiver desabilitada nas configurações do compilador.BitConverter.GetBytes(int)
quase faz o que você quer, exceto que o endianness está errado.Você pode usar o método IPAddress.HostToNetwork para trocar os bytes no valor inteiro antes de usar
BitConverter.GetBytes
ou usar a classe EndianBitConverter de Jon Skeet . Ambos os métodos fazem a coisa certa (tm) em relação à portabilidade.fonte
Quando olho para essa descrição, sinto que esse número inteiro xdr é apenas um número inteiro "padrão" big-endian, mas é expresso da maneira mais ofuscada. A notação de complemento do Two é mais conhecida como U2, e é o que estamos usando nos processadores de hoje. A ordem dos bytes indica que é uma notação big endian .
Portanto, respondendo à sua pergunta, você deve inverter os elementos em sua matriz (0 <--> 3, 1 <--> 2), pois eles são codificados em little-endian. Apenas para ter certeza, você deve primeiro verificar
BitConverter.IsLittleEndian
para ver em qual máquina está executando.fonte
Por que todo esse código nos exemplos acima ...
Uma estrutura com layout explícito atua nos dois sentidos e não tem impacto no desempenho.
Atualização: Como há uma pergunta sobre como lidar com endianness, adicionei uma interface que ilustra como abstrair isso. Outra estrutura de implementação pode lidar com o caso oposto
fonte
Se você deseja obter informações mais gerais sobre vários métodos de representação de números, incluindo o complemento de dois, consulte:
Complemento de dois e representação de número assinado na Wikipedia
fonte
A outra maneira é usar BinaryPrimitives assim
byte[] intBytes = BitConverter.GetBytes(123); int actual = BinaryPrimitives.ReadInt32LittleEndian(intBytes);
fonte
fonte
fonte
Int16
.