结构体和内存对齐

结构体和内存对齐

1.地址总线,数据总线,机器字长

地址总线:

cpu需要从内存读取数据,需要通过地址总线把地址传到内存,内存准备好数据,输出到地址总线,交给cpu,如果地址总线只有8根, 那么地址只有8为,寻址空间为256个地址,

想使用更大的内存,就需要有更宽的地址总线,32位地址总线可以寻址4G内存

数据总线,机器字长:

每次操作1字节麻烦,就加宽数据总线,一次想操作4字节,就需要用32根数据总线,每次操作字节数就是机器字长

结构体和内存对齐_第1张图片

结构体和内存对齐_第2张图片

之前有些cpu可以支持访问任意地址,是因为做了很多处理,如果想从地址1开始取8字节数据,cpu会分两次读,第一次是0-7,第二次是8-15

结构体和内存对齐_第3张图片

2.内存对齐

2.1内存对齐概念

内存对齐

计算机的内存空间是按照字节进行划分的,但是实际情况,在访问特定的变量需要在特定的地址进行访问,这就需要类型数据按照特定规则排序,而不是按照顺序一个一个存放,这种叫做内存对齐

粒度:cpu一次访问一块内存的大小,我们称之为粒度

32位CPU粒度:4字节,64位CPU粒度:8字节

内存对齐作用:减少CPU访问内存次数,提高CPU读取内存效率

2.2 确定内存对齐方法

每个类型的对齐值就是对齐边界,内存对齐要求数据存储地址以及占用字节数是对齐边界的倍数

所以int32错开两字节,从4开始存

结构体和内存对齐_第4张图片

结构体和内存对齐_第5张图片

2.3 windows64计算int8对齐边界

64位平台,最大对齐边界只有8字节,int8只有一字节,可以放在任何位置,但是会浪费7字节

结构体和内存对齐_第6张图片

2.4 windows64确定int16

int16占两字节,可以从下面地址存

结构体和内存对齐_第7张图片

int16占2字节,如果按照1字节对齐需要读两次然后拼接,浪费性能

结构体和内存对齐_第8张图片

2.5windows32确定int64

大于的情况,对齐类型大小8,需要从下图存

结构体和内存对齐_第9张图片

两字节被占用的情况,对齐到4,就要从下图开始存,浪费更少

结构体和内存对齐_第10张图片

3.确定结构体边界

第一个要求:

结构体中,成员内存对齐边界最大的那个,就是这个结构体的对齐边界

结构体和内存对齐_第11张图片

结构体和内存对齐_第12张图片

第二个要求:

结构体占用字节数需要时结构体对齐边界的倍数(结构体选成员最大对齐边界8),不够需要扩张

为什么需要限制类型大小等于对齐边界的整数倍,因为不扩大到整数倍,这个结构体类型大小就是22字节,如果后面拼接元素,那么下一个元素就对齐不了

结构体和内存对齐_第13张图片

结构体和内存对齐_第14张图片

3.2 结构体内存大小

type Student struct {
	a int8 
	b int16
}

func main() {
	var t Student
	fmt.Println(unsafe.Sizeof(t))//4
}

3.3 嵌套结构体

type Student struct {
	A
	a int8
	b int8
	c int8
	d int8
}
type A struct {
	m int8
}

func main() {
	var t Student
	fmt.Println(unsafe.Sizeof(t))//输出:5
}

3.4 结构体内存大小

type T struct {
	a int8
	b int8
	c int8
	d int8
	m int8
}

type B struct {
	*T
}

func main() {
	var b B
	fmt.Println(unsafe.Sizeof(b)) // 8
}

//匿名字段是指针,那么结构体的大小是指针的大小

你可能感兴趣的:(Golang底层,操作系统,golang)