为什么在64位架构中mod 8之后的Go的4字节对齐结构地址是4?

问题描述 投票:0回答:1

[当我同步学习代码时,WaitGroup,我注意到WaitGroup使用state1字段来确保状态可以原子存储。

喜欢这个:

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中如何保证?

代码在下面:

type M struct {
    x [3]uint32 
}
var c = M{}
println(
    unsafe.Sizeof(c),
    unsafe.Alignof(c),
    uintptr(unsafe.Pointer(&c.x)),
    uintptr(unsafe.Pointer(&c.x))%8,
)
# 64-bit arch
$ go run main.go
12 4 824634396524 4

# 32-bit arch
$ GOARCH=386 go run main.go                                                                                        
12 4 289613752 0
go 32bit-64bit memory-alignment
1个回答
0
投票

来自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
© www.soinside.com 2019 - 2024. All rights reserved.