c# .net bit-manipulation nfs

C#int a byte



.net bit-manipulation (7)

Necesito convertir un int a un byte[] Una forma de hacerlo es usar 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 número entero en el rango [-2147483648,2147483647]. El entero se representa en notación de complemento de 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?


Aquí hay otra forma de hacerlo: como todos sabemos 1x byte = 8x bits y también, un entero "normal" (int32) contiene 32 bits (4 bytes). Podemos usar el operador >> para desplazar bits a la derecha (>> el operador no cambia el valor).

int intValue = 566; byte[] bytes = new byte[4]; bytes[0] = (byte)(intValue >> 24); bytes[1] = (byte)(intValue >> 16); bytes[2] = (byte)(intValue >> 8); bytes[3] = (byte)intValue; Console.WriteLine("{0} breaks down to : {1} {2} {3} {4}", intValue, bytes[0], bytes[1], bytes[2], bytes[3]);


Cuando miro esta descripción, tengo la sensación de que este entero xdr es solo un entero "estándar" de big-endian, pero se expresa de la manera más ofuscada. La notación complementaria de dos se conoce mejor como U2, y es lo que estamos usando en los procesadores de hoy. El orden de bytes indica que es una notación big-endian .
Entonces, al responder a su pregunta, debe invertir los elementos en su matriz (0 <-> 3, 1 <-> 2), ya que están codificados en little-endian. Para asegurarse, primero debe verificar BitConverter.IsLittleEndian para ver en qué máquina se está ejecutando.


El RFC solo intenta decir que un entero con signo es un entero normal de 4 bytes con bytes ordenados en una forma de big-endian.

Ahora, probablemente trabaje en una máquina little-endian y BitConverter.GetBytes() le dará el byte[] invertido. Entonces podrías probar:

int intValue; byte[] intBytes = BitConverter.GetBytes(intValue); Array.Reverse(intBytes); byte[] result = intBytes;

Sin embargo, para que el código sea más portátil, puedes hacerlo así:

int intValue; byte[] intBytes = BitConverter.GetBytes(intValue); if (BitConverter.IsLittleEndian) Array.Reverse(intBytes); byte[] result = intBytes;


Por qué todo este código en los ejemplos de arriba ...

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 la endianidad, agregué una interfaz que ilustra cómo abstraer eso. Otra estructura de implementación puede tratar el caso opuesto

public interface IIntToByte { Int32 Int { get; set;} byte B0 { get; } byte B1 { get; } byte B2 { get; } byte B3 { get; } } [StructLayout(LayoutKind.Explicit)] public struct IntToByteLE : UserQuery.IIntToByte { [FieldOffset(0)] public Int32 IntVal; [FieldOffset(0)] public byte b0; [FieldOffset(1)] public byte b1; [FieldOffset(2)] public byte b2; [FieldOffset(3)] public byte b3; public Int32 Int { get{ return IntVal; } set{ IntVal = value;} } public byte B0 => b0; public byte B1 => b0; public byte B2 => b0; public byte B3 => b0; }



BitConverter.GetBytes(int) casi hace lo que quiere, excepto que la endianidad es incorrecta.

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.

int value; byte[] bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(value));


byte[] Take_Byte_Arr_From_Int(Int64 Source_Num) { Int64 Int64_Num = Source_Num; byte Byte_Num; byte[] Byte_Arr = new byte[8]; for (int i = 0; i < 8; i++) { if (Source_Num > 255) { Int64_Num = Source_Num / 256; Byte_Num = (byte)(Source_Num - Int64_Num * 256); } else { Byte_Num = (byte)Int64_Num; Int64_Num = 0; } Byte_Arr[i] = Byte_Num; Source_Num = Int64_Num; } return (Byte_Arr); }