内存对齐

miomiora大约 2 分钟GoGo内存对齐

未对齐

给出一个结构体

type User struct {
	A int32
	B []int32
	C string
	D bool
	E struct{}
}

算出每个字段的 sizealign

fmt.Printf("User{} size=%d, align=%d\n\n", unsafe.Sizeof(User{}), unsafe.Alignof(User{}))
fmt.Printf("int32 size=%d, align=%d\n", unsafe.Sizeof(int32(0)), unsafe.Alignof(int32(0)))
fmt.Printf("[]int32 size=%d, align=%d\n", unsafe.Sizeof(make([]int32, 0)), unsafe.Alignof(make([]int32, 0)))
fmt.Printf("string size=%d, align=%d\n", unsafe.Sizeof(""), unsafe.Alignof(""))
fmt.Printf("bool size=%d, align=%d\n", unsafe.Sizeof(true), unsafe.Alignof(true))
fmt.Printf("struct{} size=%d, align=%d\n", unsafe.Sizeof(K{}), unsafe.Alignof(K{}))

/*
    结果
	User{} size=56, align=8
	
	int32 size=4, align=4
	[]int32 size=24, align=8
	string size=16, align=8
	bool size=1, align=1
	struct{} size=0, align=1
*/

把结构体的所有字段相加的结果应该为:4 + 24 + 16 + 1 + 0 = 45

但存在结构体补 0 的情况,所以这个结构体理想的大小应该为 8 的倍数 48

分析

结构体 User 有 6 个字段,内存的分布应该为如下:

0 - 78 - 1516 - 2324 - 3132 - 3940 - 4748 - 55
00000000000000000000000000000000000000000000000000000000
11110000111111111111111111111111111111111111111110000000
int32[]int32[]int32[]int32stringstringbool struct{}

修改结构体为:

type User struct {
	A int32
	D bool
	B []int32
	C string
	E struct{}
}

在把 bool 移入到 int32 后面后,内存分布应该为

0 - 78 - 1516 - 2324 - 3132 - 3940 - 4748 - 55
00000000000000000000000000000000000000000000000000000000
11111000111111111111111111111111111111111111111100000000
int32 bool[]int32[]int32[]int32stringstringstruct{}

这么看内存应该为 48 但实际上还是 56

同时,即使 struct{}size0 也会以偏移量 1 来占用内存,多余的部分会进行补 0

对齐

修改结构体为:

type User struct {
	A int32
	D bool
	E struct{}
	B []int32
	C string
}

此时的内存分布为

0 - 78 - 1516 - 2324 - 3132 - 3940 - 4748 - 55
00000000000000000000000000000000000000000000000000000000
11111000111111111111111111111111111111111111111100000000
int32 bool struct{}[]int32[]int32[]int32stringstring

大小如愿变成了 48

上次编辑于:
贡献者: miomiora