Преобразование int [] в байт: как посмотреть на int [] как на байт []? - PullRequest
3 голосов
/ 08 января 2012

Объяснить: у меня есть массив целых чисел в качестве ввода.Мне нужно преобразовать его в массив байтов, где 1 int = 4 байта (big endian).В C ++ я легко могу привести его и затем получить доступ к полю, как если бы это был байтовый массив, без копирования или подсчета данных - просто прямой доступ.Возможно ли это в C #?А в C # 2.0?

Ответы [ 5 ]

5 голосов
/ 08 января 2012

Да, с использованием небезопасного кода:

int[] arr =...
fixed(int* ptr = arr) {
    byte* ptr2 = (byte*)ptr;
    // now access ptr2[n]
}

Если компилятор жалуется, добавьте (void*):

    byte* ptr2 = (byte*)(void*)ptr;
4 голосов
/ 08 января 2012

Вы можете создать байт [] в 4 раза больше вашей длины int [].Затем вы выполняете итерацию по целочисленному массиву и получаете массив байтов из:

BitConverter.GetBytes(int32);

Затем вы копируете 4 байта из этой функции в правильное смещение (i * 4), используя Buffer.BlockCopy.

BitConverter Buffer.BlockCopy

2 голосов
/ 08 января 2012

Посмотрите на класс BitConverter .Вы можете перебрать массив int и вызвать BitConverter.GetBytes(Int32), чтобы получить byte[4] для каждого.

1 голос
/ 08 января 2012

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

byte[] result = new byte[intArray.Length * sizeof(int)];
Buffer.BlockCopy(intArray, 0, result, 0, result.Length);

Это не совсем то, что, как я думаю, задан в вашем вопросе, поскольку на архитектурах с прямым порядком байтов (например, x86 или ARM) результирующий массив в конечном итоге будет иметь порядок байтов, но я почти уверен, что то же самое верно для C ++ а также.

Если вы можете использовать unsafe{}, у вас есть другие варианты:

unsafe{
  fixed(byte* result = (byte*)(void*)intArray){
    // Do stuff with result.
  }
}
1 голос
/ 08 января 2012

Если вы пишете небезопасный код, вы можете исправить массив в памяти, получить указатель на его начало и привести этот указатель.

unsafe
{
  fixed(int* pi=arr)
  {
    byte* pb=(byte*)pi;
    ...
  }
}

Массив в .net имеет префикс с количеством элементов, поэтому вы не можете безопасно конвертировать между int[] и byte[], которые указывают на одни и те же данные.Вы можете приводить между uint[] и int[] (по крайней мере, в отношении .net поддержка этой функции в самом C # немного противоречива).

Существуеттакже трюк на основе объединения для переинтерпретации ссылок приведения, но я настоятельно рекомендую , а не , используя его.


Обычный способ получить отдельные целые числа из байтового массива в порядке с прямым порядком байтов:BitConverter, но это относительно медленно.Ручной код часто быстрее.И, конечно, он не поддерживает обратное преобразование.

Один из способов ручного преобразования, предполагая младший порядок (при моем i3 с частотой 2,6 ГГц, около 400 миллионов операций чтения в секунду):

byte GetByte(int[] arr, int index)
{
  uint elem=(uint)arr[index>>2];
  return (byte)(elem>>( (index&3)* 8));
}

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

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

...