0%

Go内存对齐:结构体中0字节字段填充

1. 问题

观看以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

import (
"fmt"
"unsafe"
)

type S1 struct {
a struct{}
b int8
c int64
}

type S2 struct {
a int8
b int64
c struct{}
}

func main() {
var (
s1 S1
s2 S2
)
fmt.Printf("unsafe.Sizeof(s1): %v\n", unsafe.Sizeof(s1))
fmt.Printf("unsafe.Sizeof(s2): %v\n", unsafe.Sizeof(s2))
}
1.1 分析
  • S1

    1. a字段为struct{},不占内存,0字节
    2. b字段为int8,对齐长度1, 占1字节
    3. c字段为int64,对齐长度8,前两个字段只占用了1字节,所以填充7字节,对齐到八字节位

    所以S1占用16字节

  • S2

    1. a字段为int8,对齐长度1, 占1字节
    2. b字段为int64,对齐长度8,a字段只占用了1字节,所以填充7字节,对齐到八字节位
    3. a字段为struct{},不占内存,0字节

    所以S2占用16字节

真的对吗?,看看输出

1
2
unsafe.Sizeof(s1): 16
unsafe.Sizeof(s2): 24

为什么呢?我们看看golang仓库中的这个issue 9401,建议自己看比较好。

机翻一下
issue9401
那么当0字符字段在结构体最后时,多出的一个结构体对齐长度,是为了防止结构体指针之乡结构体外部,即无效指针。