【编程】C#中的结构体字节对齐

【编程】C#中的结构体字节对齐

基本原则

  1. 结构体变量的首地址能够被其对齐字节数大小所整除
  2. 成员相对结构体首地址的偏移是【当前成员对齐数】的整数倍,不满足对前一成员填充字节
  3. 结构体总大小为【最大成员对齐数】的整数倍

成员对齐数,以下三者取最小值:

  1. 类型的非托管字节数
  2. Pack值
  3. 当前环境默认对齐字节数,例如Window 64位环境下默认是8字节

从实例看注意事项

例一
    [StructLayout(LayoutKind.Sequential, Pack = 2)]
    class Foo
    {
   
        // 整型            成员大小    计算下一成员首地址    下一成员对齐数    下一成员真实首地址 
        public sbyte i1;   // 1        +0  = 1               [1]               +0 = 1 
        public byte i2;    // 1        +1  = 2               2                 +0 = 2   
        public short i3;   // 2        +2  = 4               2                 +0 = 4
        public ushort i4;  // 2        +4  = 6               2                 +0 = 6
        public int i5;     // 4        +6  = 10              2                 +0 = 10
        public uint i6;    // 4        +10 = 14              2                 +0 = 14
        public long i7;    // 8        +14 = 22              2                 +0 = 22
        public ulong i8;   // 8        +22 = 30              2                 +0 = 30
        public nint i9;    // [8]      +30 = 38              2                 +0 = 38
        public nuint i10;  // [8]      +38 = 46              2                 +0 = 46
        // 浮点型
        public float f1;   // 4        +46 = 50              2                 +0 = 50
        public double f2;  // 8        +50 = 58              2                 +0 = 58
        public decimal f3; // 16       +58 = 74              2                 +0 = 74
        // 其他
        public bool b;     // 4[1]     +74 = 78              2                 +0 = 78
        public char c;     // 1[2]     +78 = 79              [2]               +1 = 80
    }                                                        //最大成员对齐数       结构体的非托管字节数

首先看 i2 的对齐数,这个结构体定义 Pack 值为 2,byte 类型占 1 字节,我的环境是 Windows 64 默认对齐字节数是 8,三者取最小,i2 的对齐数应该 1。因此第一行中 i1 是不需要对齐的。

之后看 i9 和 i10 的对齐数,这两个类型的非托管字节数和环境有关,我的环境中是 8 字节,然而结构体开头就定义了 Pack 值为 2,取最小值仍旧会取到 2。i8 占位后,下一成员首地址为 30,能够被 2 整除。因此这一行也不需要对齐。

最后看一下 bool 和 char,这是两个很特殊的存在。如果使用 sizeof 求 bool 的字节数为 1,求 char 的字节数为 2,但是使用 Marshal.SizeOf 求 bool 的非托管字节数为 4,求 char 的非托管字节数为 1。计算字节对齐要聚焦非托管字节数,即 bool 取 4,char 取 1。

例二
    struct Bar
    {
   
        // 整型
        public sbyte i1;   // 1        +0  = 1               1                 +0  = 1
        public byte i2;    // 1        +1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值