C# 不安全值类型数组到字节数组的转换 [英] C# unsafe value type array to byte array conversions

查看:35
本文介绍了C# 不安全值类型数组到字节数组的转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用扩展方法将浮点数组转换为字节数组:

I use an extension method to convert float arrays into byte arrays:

public static unsafe byte[] ToByteArray(this float[] floatArray, int count)
{
    int arrayLength = floatArray.Length > count ? count : floatArray.Length;
    byte[] byteArray = new byte[4 * arrayLength];
    fixed (float* floatPointer = floatArray)
    {
        fixed (byte* bytePointer = byteArray)
        {
            float* read = floatPointer;
            float* write = (float*)bytePointer;
            for (int i = 0; i < arrayLength; i++)
            {
                *write++ = *read++;
            }
        }
    }
    return byteArray;
}

我知道数组是指向与元素类型和数量信息相关联的内存的指针.此外,在我看来,如果不复制上述数据,就无法进行字节数组的相互转换.

I understand that an array is a pointer to memory associated with information on the type and number of elements. Also, it seems to me that there is no way of doing a conversion from and to a byte array without copying the data as above.

我明白了吗?甚至不复制数据就无法编写IL从指针、类型和长度创建数组吗?

Have I understood this? Would it even be impossible to write IL to create an array from a pointer, type and length without copying data?

感谢您的回答,我学到了一些基础知识,并开始尝试新的技巧!

Thanks for the answers, I learned some fundamentals and got to try out new tricks!

在最初接受戴维兰德曼的回答后,我发现虽然他出色的 StructLayout hack 确实将字节数组转换为浮点数组,但反过来却行不通.演示:

After initially accepting Davy Landman's answer I found out that while his brilliant StructLayout hack does convert byte arrays into float arrays, it does not work the other way around. To demonstrate:

[StructLayout(LayoutKind.Explicit)]
struct UnionArray
{
    [FieldOffset(0)]
    public Byte[] Bytes;

    [FieldOffset(0)]
    public float[] Floats;
}

static void Main(string[] args)
{
    // From bytes to floats - works
    byte[] bytes = { 0, 1, 2, 4, 8, 16, 32, 64 };
    UnionArray arry = new UnionArray { Bytes = bytes };
    for (int i = 0; i < arry.Bytes.Length / 4; i++)
        Console.WriteLine(arry.Floats[i]);

    // From floats to bytes - index out of range
    float[] floats = { 0.1f, 0.2f, 0.3f };
    arry = new UnionArray { Floats = floats };
    for (int i = 0; i < arry.Floats.Length * 4; i++)
        Console.WriteLine(arry.Bytes[i]);
}

似乎 CLR 认为两个数组具有相同的长度.如果结构是从浮点数据创建的,字节数组的长度就太短了.

It seems that the CLR sees both arrays as having the same length. If the struct is created from float data, the byte array's length is just too short.

推荐答案

是的,类型信息和数据在同一个内存块中,所以这是不可能的,除非你覆盖浮点数组中的类型信息来欺骗系统它是字节数组.那将是一个非常丑陋的黑客攻击,并且很容易炸毁......

Yes, the type information and data is in the same memory block, so that is impossible unless you overwrite the type information in a float array to fool the system that it's byte array. That would be a really ugly hack, and could easily blow up...

如果您愿意,可以使用以下方法在不使用不安全代码的情况下转换浮点数:

Here's how you can convert the floats without unsafe code if you like:

public static byte[] ToByteArray(this float[] floatArray) {
    int len = floatArray.Length * 4;
    byte[] byteArray = new byte[len];
    int pos = 0;
    foreach (float f in floatArray) {
        byte[] data = BitConverter.GetBytes(f);
        Array.Copy(data, 0, byteArray, pos, 4);
        pos += 4;
    }
    return byteArray;
}

这篇关于C# 不安全值类型数组到字节数组的转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆