结构对齐建议? [英] Struct alignment suggestions?

查看:47
本文介绍了结构对齐建议?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过网络发送数据.为了通过网络发送该数据,我将其打包到一个字节数组中.

I am sending data over a network. To send that data over a network I am packing it into a byte array.

现在的数据类型由一个字节和 3 个浮点数组成,总共 13 个字节.要阅读本文,我需要知道结构的大小.使用 Marshal 的 sizeOf 不会返回我的序列化字节数组的正确"大小.

Right now the data type consist of a byte and 3 floats making it 13 bytes total. To read this I need to know the size of the structure. Using Marshal's sizeOf does not return the "correct" size of my serialized byte array.

现在我知道发生了什么.Marshal 正在返回我的结构的托管对齐大小.我也知道我是否标记它

Now I know what is happening. Marshal is returning me the managed aligned size of my struct. I also know if I flag it

 [StructLayout(LayoutKind.Sequential,
Pack = 1)]

然后它将返回正确"的大小.我的问题是最好的方法是什么?我知道它添加填充位的原因是因为处理器喜欢对齐所有内容(如果我没有记错,请随时纠正我!)

then it will return the "correct" size. My question is what is the best approach? I know the reason it adds in the padding bits is because the processor likes everything to be aligned (if I'm not mistaken, feel free to correct me!)

性能损失是否值得这样做,所以我可以使用 sizeof 来反序列化数组,或者最好使用我自己计算大小的常量来从数组中读取,或者采取几个字节的大小损失通过填充在我的数组中(我最不喜欢的选项.)

Is the performance penalty worth doing this so I can use sizeof to deserialize the array, or would it be better to use a constant that I calculate in size myself to read from the array, or take a size penalty of a few bytes in my array by padding it (my least favorite option.)

如果我对为什么 Marshal 想要对齐内存或其他任何事情有误解,请随时启发我,并就哪种方法最好给我建议.

If there is something I'm misunderstanding about why Marshal wants to align the memory or anything else please feel free to enlighten me and give me suggestions as to which approach is the b est.

推荐答案

我正在通过网络发送数据.为了通过网络发送该数据,我将其打包成一个字节数组.

I am sending data over a network. To send that data over a network I am packing it into a byte array.

不要这样做.

MarshalStructLayout 旨在用于本机互操作,而不是用于网络 IO 和序列化.

Marshal and StructLayout is intended for native interop use, not for network IO and seralization.

为 IO 序列化对象实例的正确方法是手动编写它,这样您就可以精确控制序列化表示并可以保证正确的格式(直接向下多字节值的字节序).使用 BinaryWriter(或者更好的是 Jon Skeet 的 MiscUtil.EndianBinaryReader:http://jonskeet.uk/csharp/miscutil/).

The correct way to serialize an object instance for IO is to write it manually, that way you get precise control over the serialized representation and can guarantee the correct format (right down the endianness of multi-byte values). Use a BinaryWriter (or better yet, Jon Skeet's MiscUtil. EndianBinaryReader: http://jonskeet.uk/csharp/miscutil/ ).

struct Foo {
    public const  Int32 Size = sizeof(Byte) + (sizeof(Single) * 3);
    public Byte   B;
    public Single F1;
    public Single F2;
    public Single F3;

    public void Serialize(EndianBinaryWriter wtr) {
        wtr.Write( Size );
        wtr.Write( B );
        wtr.Write( F1 );
        wtr.Write( F2 );
        wtr.Write( F3 );
    }

    public static Foo Deserialize(EndianBinaryReader rdr) {
        if( rdr.ReadInt32() != Size ) throw new ...
        Foo f;
        f.B  = rdr.ReadByte();
        f.F1 = rdr.ReadSingle();
        f.F2 = rdr.ReadSingle();
        f.F3 = rdr.ReadSingle();
        return f;
    }
}

将此视为一种 ISerializable-lite.您可以在网络程序中使用它,方法是拥有一个对应于您的开放网络套接字连接的 Stream 对象,然后将其包装在 EndianBinaryWriter|Reader 对象周围并通过执行所有 IO 操作那些对象.作为奖励,您可以免费获得磁盘序列化:只需使用 FileStream 而不是网络流.

Think of this as a kind-of ISerializable-lite. You would use this in a network program by having a Stream object that corresponds to your open network socket connection then wrapping it around the EndianBinaryWriter|Reader objects and doing all IO operations through those objects. As a bonus, you get disk serialization for free: just use a FileStream instead of a network stream.

这篇关于结构对齐建议?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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