我有struct
:
[StructLayout(LayoutKind.Explicit)]
private struct Test
{
[FieldOffset(0)]
public readonly short Foo;
[FieldOffset(2)]
public readonly short Bar;
[FieldOffset(4)]
public readonly short Baz;
}
以下字节数组:
var bytes = new byte[]
{
0x00, 0x01,
0x00, 0x05,
0xFF, 0xFB
};
我将我的字节数组转换为具有以下辅助函数的结构:
private static T ByteArrayToStructure<T>(byte[] bytes)
where T : struct
{
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try
{
return (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally
{
handle.Free();
}
}
所以我按如下方式使用它:
var test = ByteArrayToStructure<Test>(bytes);
Assert.AreEqual(1, test.Foo);
Assert.AreEqual(5, test.Bar);
Assert.AreEqual(-5, test.Baz);
现在看看Asserts,我们可以清楚地看到我所期待的,如果结果不是这样的话,这个问题就会在这里。
似乎某些东西正在翻转2个字节,因此对于第一个字节,它是0x0100
而不是0x0001
,对于第二个字节,它出现为0x0500
而不是0x0005
{1}},最后一个显示为0xFBFF
而不是0xFFFB
。
有没有办法禁用此行为?
谢谢!
答案 0 :(得分:0)
如果您想更改数据的字节顺序,这还不够:
Array.Reverse(data);
Test t = ByteArrayToStructure<Test>(bytes);
从那时起,您还将获得结构值的相反顺序:
t.Foo will be -5
t.Bar will be 5
t.Baz will be 1
只有知道结构中每个字段的大小,才能反转数组的字节顺序,这样才能有选择地反转数组中各自的字节块。或者,您应该在从阵列封送后对结构的每个字段执行字节交换,如下所示:
Test t = ByteArrayToStructure<Test>(bytes);
t.Foo = SwapBytes(t.Foo);
t.Bar = SwapBytes(t.Bar);
t.Baz = SwapBytes(t.Baz);
private static short SwapBytes(short value)
{
return (short)((value >> 8) | ((value & 0xFF) << 8));
}
但我认为如果你需要这样做,代码的逻辑是有缺陷的。
我找到了许多替代解决方案,比如@Sam Ax在他的推荐中发布的解决方案,或this one ......但我仍然认为这不是一个好习惯。