解释一下:我有一个整数数组作为输入。我需要将它转换成字节数组,其中1个整数=4个字节(大端)。在C++中,我可以轻松地进行强制类型转换,然后像访问字节数组一样访问字段,而不用复制或计算数据——直接访问即可。在C#中是否也可以实现这种操作?并且在C# 2.0中是否也可以实现?
是的,可以使用不安全的代码:
int[] arr =...
fixed(int* ptr = arr) {
byte* ptr2 = (byte*)ptr;
// now access ptr2[n]
}
(void*)
: byte* ptr2 = (byte*)(void*)ptr;
BitConverter.GetBytes(int32);
i
作为右值,也是访问变量的最小可能方式,会复制它的值。 - David Schwartzref i
不会复制该值 :p - Marc Gravellref
)- 这实际上是一个严肃的问题,因为在 struct
的情况下,您可以使用 ref
将地址传递给方法,然后在方法内部访问成员和调用方法,而不必复制该值。这种方法在 XNA 中很常见,因为 struct
是常见的避免 GC 的方式。 - Marc Gravellint
毕竟没有任何成员),但显然OP谈到了拥有一个完整副本的数组,而不是在CPU寄存器等地方临时复制单个值。 - CodesInChaos如果你编写不安全的代码,你可以修复内存中的数组,获取指向其开头的指针,并将该指针强制转换。
unsafe
{
fixed(int* pi=arr)
{
byte* pb=(byte*)pi;
...
}
}
int[]
和 byte[]
之间进行转换。您可以在 uint[]
和 int[]
之间进行强制类型转换(至少就 .net 而言,C#本身对此特性的支持有些不一致)。BitConverter
,但它相对较慢。手动编写的代码通常更快。当然,它也不支持反向转换。byte GetByte(int[] arr, int index)
{
uint elem=(uint)arr[index>>2];
return (byte)(elem>>( (index&3)* 8));
}
如果你想使用托管代码,我建议手动编写使用位移操作来访问单个字节的代码;如果你想追求最后一点性能,则需要使用指针。
此外,你还需要注意字节序问题。其中一些方法仅支持本机字节序。
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.
}
}
BlockCopy
使用本地字节顺序,而不是小端字节顺序。当然,CLR通常运行在小端架构上,因此实际上很少有区别。 - CodesInChaos