天天看点

go 地址对齐保证

unsafe标准库包

​func Alignof(variable ArbitraryType) uintptr​

​​。 此函数用来取得一个值在内存中的地址对齐保证(address alignment guarantee)。 注意,同一个类型的值做为结构体字段和非结构体字段时地址对齐保证可能是不同的。 当然,这和具体编译器的实现有关。对于目前的标准编译器(go 1.18),同一个类型的值做为结构体字段和非结构体字段时的地址对齐保证总是相同的。 ​

​gccgo​

​编译器对这两种情形是区别对待的。

package main

import (
  "fmt"
  "unsafe"
)

func main() {
  var x struct {
    a int64
    b bool
    c string
  }
  fmt.Println(unsafe.Alignof(x.a)) //8
  fmt.Println(unsafe.Alignof(x.b)) //1
  fmt.Println(unsafe.Alignof(x.c)) //8
}      

地址对齐保证

为了充分使用​

​CPU​

​​的指令并获得最佳性能,为给指定类型的值分配的内存块(起始)地址必须是一个整数​

​N​

​​的倍数,则​

​N​

​​称为该类型的值的(内存)地址对齐保证,或者简单的称为该类型的对齐保证。我们也可以说,这个类型的可寻址值的地址确保是​

​N​

​字节对齐的。

事实上,每种类型拥有两个对其保证,一种当它作为其他类型​

​(struct)​

​的字段,另一种是针对其他情况(如当它作为一个变量的声明,数组元素的类型等等)。我称前者为类型的字段对齐保证,而称后者为类型的一般对齐保证。

对于一种类型,我们可以调用​

​unsafe.Algnof(t)​

​​去获取它的一般对齐保证,其中​

​t​

​​是​

​T​

​​类型的无字段值,也可以调用​

​unsafe.Algnof(x.t)​

​​去获取它字段的对齐保证,其中​

​x​

​​是一个​

​struct​

​​的值,同时​

​a​

​​是类型​

​T​

​的字段值。

标准库​

​unsafe​

​中的函数调用总是在编译期间。