Pz.
Pz.

Reputation: 1179

Converting int[] to byte: How to look at int[] as it was byte[]?

To explain: I have array of ints as input. I need to convert it to array of bytes, where 1 int = 4 bytes (big endian). In C++, I can easily just cast it and then access to the field as if it was byte array, without copying or counting the data - just direct access. Is this possible in C#? And in C# 2.0?

Upvotes: 3

Views: 906

Answers (5)

sblom
sblom

Reputation: 27343

The simplest way in type-safe managed code is to use:

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

That doesn't quite do what I think your question asked, since on little endian architectures (like x86 or ARM), the result array will end up being little endian, but I'm pretty sure the same is true for C++ as well.

If you can use unsafe{}, you have other options:

unsafe{
  fixed(byte* result = (byte*)(void*)intArray){
    // Do stuff with result.
  }
}

Upvotes: 1

CodesInChaos
CodesInChaos

Reputation: 108800

If you write unsafe code, you can fix the array in memory, get a pointer to its beginning, and cast that pointer.

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

An array in .net is prefixed with the number of elements, so you can't safely convert between int[] and byte[] that points to the same data. You can cast between uint[] and int[] (at least as far as .net is concerned, the support for this feature in C# itself is a bit inconsistent).

There is also a union based trick to reinterpret cast references, but I strongly recommend not using it.


The usual way to get individual integers from a byte array in native-endian order is BitConverter, but its relatively slow. Manual code is often faster. And of course it doesn't support the reverse conversion.

One way to manually convert assuming little-endian (managed about 400 million reads per second on my 2.6GHz i3):

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

I recommend manually writing code that uses bitshifting to access individual bytes if you want to go with managed code, and pointers if you want the last bit of performance.

You also need to be careful about endianness issues. Some of these methods only support native endianness.

Upvotes: 1

Marc Gravell
Marc Gravell

Reputation: 1062820

Yes, using unsafe code:

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

If the compiler complains, add a (void*):

    byte* ptr2 = (byte*)(void*)ptr;

Upvotes: 5

Cedric Van Goethem
Cedric Van Goethem

Reputation: 121

You can create a byte[] 4 times the size of your int[] lenght. Then, you iterate trough your integer array & get the byte array from:

BitConverter.GetBytes(int32);

Next you copy the 4 bytes from this function to the correct offset (i * 4) using Buffer.BlockCopy.

BitConverter Buffer.BlockCopy

Upvotes: 4

Jonathon Reinhart
Jonathon Reinhart

Reputation: 137408

Have a look at the BitConverter class. You could iterate through the array of int, and call BitConverter.GetBytes(Int32) to get a byte[4] for each one.

Upvotes: 2

Related Questions