写点什么

golang 结构体内存对齐

作者:fm
  • 2023-10-31
    广东
  • 本文字数:955 字

    阅读完需:约 3 分钟

计算机字长就是计算机中 CPU 在一次操作中能处理的单位字的长度,即运算器能够并行处理和存储器每次读写操作时能包含的二进制码的位数。

32 位处理器单次读写字长为 4 字节,64 位处理器单次读写字长为 8 字节。

以 64 位系统为例。

type A struct{	a bool  b string}
复制代码

结构体 A 未进行内存对齐时,读取 b 的值,需要两次读取再拼接;

内存对齐之后,读取 b 的值仅需要一次读取,但会浪费 7bytes 的内存空间。

再看一个 golang struct

type A struct {	a bool	b string	c int8	d string	e int64}
func main() { a := A{ a: false, b: "春天", c: 0, d: "深圳市罗湖区", e: 0, } fmt.Printf("struct:%s,size:%d \n", "A", unsafe.Sizeof(a)) fmt.Printf("property:%s,size:%d,offset:%d \n", "a", unsafe.Sizeof(a.a), unsafe.Offsetof(a.a)) fmt.Printf("property:%s,size:%d,offset:%d \n", "b", unsafe.Sizeof(a.b), unsafe.Offsetof(a.b)) fmt.Printf("property:%s,size:%d,offset:%d \n", "c", unsafe.Sizeof(a.c), unsafe.Offsetof(a.c)) fmt.Printf("property:%s,size:%d,offset:%d \n", "d", unsafe.Sizeof(a.d), unsafe.Offsetof(a.d)) fmt.Printf("property:%s,size:%d,offset:%d \n", "e", unsafe.Sizeof(a.e), unsafe.Offsetof(a.e))}
复制代码

运行结果:

struct:A,size:56property:a,size:1,offset:0  // size = 1, padding bytes = 7property:b,size:16,offset:8  //size = 16 ,padding bytes = 0property:c,size:1,offset:24   //size = 1 ,padding bytes = 7property:d,size:16,offset:32  //size = 16 ,padding bytes = 0property:e,size:8,offset:48    //size = 8 ,padding bytes = 0
复制代码

为达到内存对齐的目的,再 a 和 c 后面增加了 14 个填充 bytes。

修改结构体 A,改变属性的顺序

type A struct {	a bool  c int8	b string	d string	e int64}
复制代码

再次执行程序,结果:

struct:A,size:48property:a,size:1,offset:0   property:b,size:16,offset:8  property:c,size:1,offset:1   //offset:1 property:d,size:16,offset:24 property:e,size:8,offset:40  
复制代码

结构体的属性值在内存中按照结构体定义的先后顺序连续存储,现在属性 c 的 offset = 1,它直接跟在属性 a 的后面,属性 a 后面并没有填充 bytes。通过改变属性的顺序将结构体的 size 从 56 减少到 48。


用户头像

fm

关注

还未添加个人签名 2019-12-16 加入

还未添加个人简介

评论

发布
暂无评论
golang结构体内存对齐_fm_InfoQ写作社区