为什么结构中“[0]byte”的位置很重要?

2024-05-12

[0]byte在golang中不应该占用任何内存空间。但这两个结构体的大小不同。

type bar2 struct {
    A int
    _ [0]byte
}

type bar3 struct {
    _ [0]byte
    A int   
}

那么为什么这个位置[0]byte这里重要吗?

顺便说一句,我用unsafe.Sizeof()检查结构大小的方法。请参阅完整的例子 https://play.golang.org/p/oAnH2XodPa .


这是由于一个tricky填充。

首先,请允许我稍微重命名结构和字段,以便更容易讨论它们:

type bar1 struct {
    A [0]byte
    I int
}

type bar2 struct {
    I int
    A [0]byte
}

这当然不会改变大小和偏移量,可以在去游乐场 https://play.golang.org/p/NcTeFpDrJi:

bar1 size:     4
bar1.A offset: 0
bar1.I offset: 0

bar2 size:     8
bar2.I offset: 0
bar2.A offset: 4

类型值的大小[0]byte为零,因此它完全有效bar1不为第一个字段保留任何空间(bar1.A),并布置bar1.I偏移量为 0 的字段。

问题是:为什么编译器不能在第二种情况下做同样的事情(使用bar2)?

字段必须有一个地址,该地址必须位于为前一个字段保留的存储区域之后。在第一种情况下,第一个字段bar1.A大小为 0,因此第二个字段的偏移量可能为 0,它不会与第一个字段“重叠”。

的情况下bar2,第二个字段不能有与第一个字段重叠的地址(因此也有偏移量),因此它的偏移量不能小于int在 32 位架构中为 4 个字节(在 64 位架构中为 8 个字节)。

这看起来还是可以的。但是由于bar2.A大小为零,为什么结构体的大小不能bar2就是这样:4 个字节(或 64 位架构中的 8 个字节)?

这是因为它是完美的有效获取大小为 0 的字段(和变量)的地址。好吧,那又怎么样?

的情况下bar2,编译器必须插入 4(或 8)字节填充,否则采用 a 的地址bar2.A字段会指向内存区域之外为类型值保留bar2.

举个例子,无填充值为bar2可能有一个地址0x100,大小为 4,因此为结构体值保留的内存具有地址范围0x100 .. 0x103。地址bar2.A将会0x104,即在结构体内存之外。如果是此结构的数组(例如x [5]bar2),如果数组开始于0x100,地址x[0]将会0x100,地址x[0].A将会0x104,以及后续元素的地址x[1]也会是0x104但这是另一个结构体值的地址!不酷。

为了避免这种情况,编译器插入一个填充(根据架构,该填充将是 4 或 8 字节),以便获取bar2.A不会导致地址位于结构体内存之外,否则可能会引发问题并导致垃圾收集方面的问题(例如,如果只有bar2.A被保留,但不保留结构或指向它或其其他字段的另一个指针,整个结构不应被垃圾收集,但由于没有指针指向其内存区域,因此这样做似乎是有效的)。插入的填充将为 4(或 8)字节,因为规格:尺寸和对齐保证: https://golang.org/ref/spec#Size_and_alignment_guarantees

对于一个变量x结构类型:unsafe.Alignof(x)是所有值中最大的unsafe.Alignof(x.f)对于每个字段f of x, 但至少1.

如果是这样,添加一个额外的int字段将使两个结构的大小相等:

type bar1 struct {
    I int
    A [0]byte
    X int
}

type bar2 struct {
    A [0]byte
    I int
    X int
}

事实上,它们在 32 位架构上都有 8 个字节(在 64 位架构上都有 16 个字节)(在去游乐场 https://play.golang.org/p/SBweaAzE2b):

bar1 size:     8
bar1.I offset: 0
bar1.A offset: 4
bar1.X offset: 4

bar2 size:     8
bar2.A offset: 0
bar2.I offset: 0
bar2.X offset: 4

查看相关问题:如果字段顺序不同,结构体的大小也不同 https://stackoverflow.com/questions/34219232/struct-has-different-size-if-the-field-order-is-different/34219916#34219916

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么结构中“[0]byte”的位置很重要? 的相关文章

随机推荐