C#StructLayout / FieldOffset和索引数组 [英] C# StructLayout/FieldOffset and indexing in arrays

查看:288
本文介绍了C#StructLayout / FieldOffset和索引数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一点正确使用FieldOffset数组的问题。下面的code是一个例子,它正确地对我不起作用:

I'm having a bit of a problem using FieldOffset correctly with arrays. The code below is an example where it doesn't work correctly for me:

[StructLayout(LayoutKind.Explicit)]
public struct IndexStruct {
	[FieldOffset(0)]
	public byte[] data;

	[FieldOffset(0)]
	public short[] idx16;

	[FieldOffset(0)]
	public int[] idx32;
}

如果我的示例设置名为数据为序列化的字节数组的数组,然后尝试检索数据,使用idx16字段索引仍然排列为一个byte []短裤。也就是说idx16 [1]取在数据中的第二字节,而不是第二16位字(字节2和3)。如果我做的逆I指数短裤而不是字节,这意味着偏移对准从源数据继承。我的问题,是有办法解决此问题?我知道,我可以通过与元件的尺寸乘以补偿索引值,但有另一种方式?

If I for example sets the array named "data" to a serialized byte array and then try to retrieve data as shorts using the "idx16" field the indexing is still aligned as a byte[]. Meaning that idx16[1] fetches the second byte in data, not the second 16bit word (byte 2 and 3). If I do the inverse I index shorts instead of bytes, meaning that the offset alignment is inherited from the source data. My question, is there a way to work around this? I know that I can compensate the index value by multiplying with the size of the element, but is there another way?

<一个href="http://stackoverflow.com/questions/619041/what-is-the-fastest-way-to-convert-a-float-to-a-byte/619307#619307">Here一个答案,我发现这里的计算器,但在尝试了$ C $当c事实证明,它不能正常工作。使用单元测试VS具有以下code没有任何成功尝试过了:

Here is an answer I found here on StackOverflow, but when trying that code it turned out that it wasn't working properly. Tried it out using a Unit test in VS with the following code without any success:

[TestMethod()]
public void SumTest() {
    float[] fArr = {2.0f, 0.5f, 0.0f, 1.0f};
    MemoryStream ms = new MemoryStream();
    for (int i = 0; i < fArr.Length; i++) {
    	ms.Write(BitConverter.GetBytes(fArr[i]), 0, sizeof(float));
    }
    byte[] buff = ms.ToArray();
    double expected = 3.5f;
    double actual = Sum(buff);
    Assert.AreEqual(expected, actual);
}

提前感谢!

推荐答案

现在的问题是(从我所看到的),你已经联合在一起在引用的阵列 - 故取其数组被设置最后会赢。一旦有一个阵列,它是一个使用索引(未字节偏移) - 这样的大小也没有关系

The problem is (from what I can see) that you've unioned the references of the arrays - so whichever array gets set last will win. Once there is an array, it is using the indexer (not byte offset) - so the size doesn't matter.

的方式做到这一点正确(或不正确,视情况而定)很可能是不安全code - 以指向数组 - 是这样的:

The way to do this "properly" (or improperly, as the case may be) would probably be with unsafe code - taking the pointer to the array - something like:

    IndexStruct s = new IndexStruct();
    s.data = new byte[] { 1, 0, 0, 0, 1, 1 };

    unsafe
    {
        fixed (short* data = s.idx16)
        {
            Console.WriteLine(data[0]); // should be 1 (little-endian)
            Console.WriteLine(data[1]); // should be 0
            Console.WriteLine(data[2]); // should be 257
        }
    }

当然,我不知道我推荐它 - 但似乎达到你想要的东西。

Of course, I'm not sure I recommend it - but that seems to achieve what you want?

我也想知道是否可以删除结构彻底和公正的使用不安全的访问字节[] 直接

I also wonder whether you can drop the struct completely and just use unsafe access to a byte[] directly:

    byte[] raw = new byte[] { 1, 0, 0, 0, 1, 1 };
    unsafe
    {
        fixed (byte* addr = raw)
        {
            short* s = (short*)addr;
            Console.WriteLine(s[0]); // should be 1
            Console.WriteLine(s[1]); // should be 0
            Console.WriteLine(s[2]); // should be 257
        }
    }

这篇关于C#StructLayout / FieldOffset和索引数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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