Necesito convertir una int
en una byte[]
forma de hacerlo es usarla BitConverter.GetBytes()
. Pero no estoy seguro si eso coincide con la siguiente especificación:
Un entero con signo XDR es un dato de 32 bits que codifica un entero en el rango [-2147483648,2147483647]. El entero se representa en notación de complemento a dos. Los bytes más y menos significativos son 0 y 3, respectivamente. Los enteros se declaran de la siguiente manera:
Fuente: RFC1014 3.2
¿Cómo podría hacer una transformación int a byte que satisfaga la especificación anterior?
c#
.net
bit-manipulation
nfs
Peter
fuente
fuente
Respuestas:
El RFC solo está tratando de decir que un entero con signo es un entero normal de 4 bytes con bytes ordenados de forma big endian.
Ahora, lo más probable es que esté trabajando en una máquina little-endian y
BitConverter.GetBytes()
le dará labyte[]
inversión. Entonces podrías probar:Sin embargo, para que el código sea más portátil, puede hacerlo así:
fuente
byte[] result = intBytes;
? ¿No esintBytes
ya la matriz que quieres?result
es redundante en este código. Sin embargo, sentí que era más pedagógico mostrar explícitamente al lector cuál era el resultado que suponer que pueden darse cuenta de que el resultado está contenido en alguna variable nombradaintBytes
. Además, hacer la asignación es barato ya que no copia la memoria ni asigna nueva memoria, simplemente agrega un nuevo nombre a la matriz ya asignada. Entonces por qué no hacerlo?Aquí hay otra forma de hacerlo: como todos sabemos 1x byte = 8x bits y también, un entero "regular" (int32) contiene 32 bits (4 bytes). Podemos usar el operador >> para desplazar los bits a la derecha (el operador >> no cambia el valor).
fuente
& 0xFF
bits son innecesarios.unchecked
bloque. Actualmente solo funciona si la comprobación de desbordamiento de enteros está deshabilitada en la configuración del compilador.BitConverter.GetBytes(int)
casi hace lo que quieres, excepto que el endianness está mal.Puede usar el método IPAddress.HostToNetwork para intercambiar los bytes dentro del valor entero antes de usar
BitConverter.GetBytes
o usar la clase EndianBitConverter de Jon Skeet . Ambos métodos hacen lo correcto (tm) con respecto a la portabilidad.fuente
Cuando miro esta descripción, tengo la sensación de que este entero xdr es solo un entero "estándar" big endian, pero se expresa de la manera más ofuscada. Notación de complemento a dos se conoce mejor como U2, y es lo que estamos usando en los procesadores de hoy. El orden de los bytes indica que es una notación big-endian .
Entonces, respondiendo a su pregunta, debe invertir elementos en su matriz (0 <--> 3, 1 <--> 2), ya que están codificados en little-endian. Solo para asegurarse, primero debe verificar
BitConverter.IsLittleEndian
para ver qué máquina está ejecutando.fuente
¿Por qué todo este código en los ejemplos anteriores ...
Una estructura con diseño explícito actúa en ambos sentidos y no tiene impacto en el rendimiento.
Actualización: dado que hay una pregunta sobre cómo lidiar con el endianness, agregué una interfaz que ilustra cómo abstraer eso. Otra estructura de implementación puede tratar el caso contrario
fuente
Si desea información más general sobre varios métodos para representar números, incluido el Complemento de dos, eche un vistazo a:
Complemento de dos y representación de números firmados en Wikipedia
fuente
La otra forma es usar BinaryPrimitives así
byte[] intBytes = BitConverter.GetBytes(123); int actual = BinaryPrimitives.ReadInt32LittleEndian(intBytes);
fuente
fuente
fuente
Int16
.