系统相关
首页 > 系统相关> > unsafe和在Go中的内存对齐

unsafe和在Go中的内存对齐

作者:互联网

unsafe包和在Go中的内存对齐

unsafe包

unsafe包提供了一些跳过Go语言类型安全限制的操作 其中包括两种类型和三个函数

 type AribitraryType  //可以是任何一种类型
 例如:
 type AribitraryType int //int类型
 ​
 指针 Go语言指针只支持取地址和解引用 不支持运算
 type Pointer *ArbitraryType
 ​
 Pointer表示任意类型的指针
 1.任意类型指针可以转换为Pointer类型值
 2.一个pointer可以转换为任意类型的指针
 ​
 ​
 ​
 func Sizeof(v ArbitraryType) uintptr
 ​
 //返回类型v本身数据所占用的字节数,注意这里的返回值是顶层数据占有的字节数
 比如v如果是一个切片,那么它会返回该切片描述符的大小,而非是该切片底层引用内存的大小
 ​
 ​
 func Aligof(v ArbitraryType) uintptr//返回类型v的对齐方式(在内存中占用的字节数),如果是结构体类型的字段的形式,它会返回字段f在该结构体中的对齐方式
 ​
 ​
 func Offsetof(v ArbitraryType) unitptr
 //返回类型v所代表的结构体字段在结构体中的偏移量,v必须是结构体类型的字段形式

 

内存对齐

很早以前就存在一个问题,为什么将元素一个个append进切片,那么是满足cap*2规律,而一次性append多个数就不满足呢?这就要提到内存对齐了

在cpu中内存是一块一块读取,而不是一个个二进制字节数组读取的,块的大小可以为2、4、6、8等,块的大小被我们称为内存访问粒度imgimg内存对齐的优点:对于为对齐的内存,将会导致cpu进行两次内存访问,并且需要消耗多余的时间和资源进行对齐运算,如果是已经对齐的内存,那么cpu仅需要一次访问就可以完成读取动作

对齐规则

 type Part1 struct {
    a bool
    b int32
    c int8
    d int64
    e byte
 }
 //1+4+1+8+1=15 ?
 ​
 但是如果我们用sizeof函数测试
 ​
 fmt.Printf("part1 size: %d, align: %d\n", unsafe.Sizeof(part1), unsafe.Alignof(part1))
 //part1 size: 32, align: 8
 ​
 ​
 ​
 ​
 func main() {
    fmt.Printf("bool align: %d\n", unsafe.Alignof(bool(true)))
    fmt.Printf("int32 align: %d\n", unsafe.Alignof(int32(0)))
    fmt.Printf("int8 align: %d\n", unsafe.Alignof(int8(0)))
    fmt.Printf("int64 align: %d\n", unsafe.Alignof(int64(0)))
    fmt.Printf("byte align: %d\n", unsafe.Alignof(byte(0)))
    fmt.Printf("string align: %d\n", unsafe.Alignof("EDDYCJY"))
    fmt.Printf("map align: %d\n", unsafe.Alignof(map[string]string{}))
 }
 //bool align: 1
 int32 align: 4
 int8 align: 1
 int64 align: 8byte align: 1string align: 8
 map align: 8
 ​
 在Go中可以调用unsafe.Alignof来返回相应类型的对其系数 这些系数是2^n,最大不会超过八。这是因为一般编译器的默认对齐系数是8
 ​
 在上述结构体中,每个结构体中的变量要做字节对齐,而最终结果的结构体也需要做字节对齐
 ​
 ​
 ​
 ​
 type Part1 struct {
    a bool
    b int32
    c int8
    d int64
    e byte
 }
 // a bool 占用1 对齐到4
 // b int32 占用8 不对齐
 // c int8 占用9 对齐到16
 // d int64 占用24 不对齐
 // e byte 占用25 对齐到32  
 // 总占用32
 ​
 ​
 ​
 type Part2 struct {
    e byte
    c int8
    a bool
    b int32
    d int64
 }
 // e byte 占用1 不对齐
 // c int8 占用2 不对齐‘
 // a bool 占用3 对齐到4
 // b int32 占用8 不对齐
 // d int64 占用16 不对齐
 //总占用16

简单改变一下结构体成员的字段顺序就改变了结构体占用大小

标签:Alignof,align,unsafe,内存,Go,对齐,占用
来源: https://www.cnblogs.com/bokeofcxs/p/15748343.html