当我研究sync.WaitGroup中的代码时,
我注意到WaitGroup使用state1([3] uint32)字段假定状态原子存储的64位对齐指针。
像这样:
// https://github.com/golang/go/issues/19149
type WaitGroup struct {
noCopy noCopy
state1 [3]uint32
}
// state returns pointers to the state and sema fields stored within wg.state1.
func (wg *WaitGroup) state() (statep *uint64, semap *uint32) {
if uintptr(unsafe.Pointer(&wg.state1))%8 == 0 {
return (*uint64)(unsafe.Pointer(&wg.state1)), &wg.state1[2]
} else {
return (*uint64)(unsafe.Pointer(&wg.state1[1])), &wg.state1[0]
}
}
但是当我在Mac和Linux上检查时,
在64位系统上,在mod 8之后显示的第一个分配的4字节对齐数据结构地址是 4 ,而在32位系统上,它是 0 。
我很好奇golang如何保证?
代码在这里:https://play.golang.org/p/oiZMHd2c0I6
// 32-bit system:
// GOARCH=386 go run main.go
// 0 4 0 //why first address mod 8 is 0
// 64-bit system:
// go run main.go
// 4 0 4 //why first address mod 8 is 4
更新:
使用@Renat的答案地址,就不能保证变量地址。
输出可能不包含在内。
最佳答案
从golang.org:
计算机体系结构可能需要对齐内存地址;
也就是说,如果变量的地址是某个因子的倍数,则
变量类型的对齐方式。 Alignof函数接受一个表达式
表示任何类型的变量,并返回(type
的变量(以字节为单位)。
因此,假设Alignof(c)
是4
,它将与4
对齐,而不必与8
字节对齐。
当创建另一个M
对象
var c = M{}
var d = M{}
println(
unsafe.Sizeof(c),
unsafe.Alignof(c),
uintptr(unsafe.Pointer(&c.x))%8,
)
println(
" ",
uintptr(unsafe.Pointer(&d.x))%8,
)
我有:
12 4 4
0
关于go - 为什么在64位arch中mod 8为4后Go的4bytes对齐结构地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60165649/