C# int в байт[]


мне нужно преобразовать int до byte[] один из способов-это использовать BitConverter.GetBytes(). Но я не уверен, что это соответствует следующей спецификации:

целое число со знаком XDR является 32-разрядным датумом, который кодирует целое число в диапазон [-2147483648,2147483647]. Целое число представлено в виде два дополнения нотации. Наиболее и наименее значимый байт 0 и 3 соответственно. Целые числа объявляются следующим образом:

источник: RFC1014 3.2

как я могу сделать преобразование int в байт, которое удовлетворяло бы приведенной выше спецификации?

7 141

7 ответов:

RFC просто пытается сказать, что целое число со знаком является нормальным 4-байтовым целым числом с байтами, упорядоченными по большому концу.

теперь вы, скорее всего, работаете на машине little-endian и BitConverter.GetBytes() даст вам byte[] отменено. Так что вы можете попробовать:

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

для кода, чтобы быть наиболее портативным, однако, вы можете сделать это следующим образом:

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

вот еще один способ сделать это: как мы все знаем, 1X байт = 8X бит, а также "обычное" целое число (int32) содержит 32 бита (4 байта). Мы можем использовать оператор > > для сдвига битов вправо (>>оператор не изменяет значение.)

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]);

BitConverter.GetBytes(int) почти делает то, что вы хотите, за исключением endianness неправильно.

можно использовать IPAddress.HostToNetwork метод для замены байтов в целочисленном значении перед использованием BitConverter.GetBytes или использовать Джона Скита EndianBitConverter class. Оба метода делают правильную вещь (tm) относительно переносимости.

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

когда я смотрю на это описание, у меня есть ощущение, что это целое число xdr-это просто большое "стандартное" целое число, но оно выражено самым запутанным образом. два дополнения нотации лучше знать, как U2, и это то, что мы используем на сегодняшний процессоров. Порядок байтов указывает, что это big-endian нотации.
Итак, отвечая на ваш вопрос, вы должны инвертировать элементы в своем массиве (0 3, 1 2), как они закодированы в little-endian. Просто чтобы убедиться, вы должны сначала проверить BitConverter.IsLittleEndian чтобы увидеть, на какой машине вы работаете.

Если вы хотите получить более общую информацию о различных методах представления чисел, включая дополнение двух, посмотрите:

дополнение и Представление Подписанного Числа Википедии

почему весь этот код в примерах выше...

структура с явным макетом действует в обоих направлениях и не имеет хита производительности.

Update: поскольку есть вопрос о том, как бороться с endianness, я добавил интерфейс, который иллюстрирует, как абстрагироваться от этого. Другая реализующая структура может иметь дело с противоположным случаем

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; 
}
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);
}