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

当我研究 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 位系统上,第一个分配的 4 字节对齐数据结构地址显示在 mod 8 之后是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 的答案地址,不能保证变量地址。输出可能不包含。


翻过高山走不出你
浏览 112回答 1
1回答

收到一只叮咚

来自golang.org:计算机架构可能需要对齐内存地址;也就是说,对于一个变量的地址是一个因子的倍数,变量的类型的对齐。函数 Alignof 接受一个表示任何类型变量的表达式,并以字节为单位返回变量(类型)的对齐方式。Alignof(c)因此,鉴于4,它将与 对齐4,而不是与8字节对齐。当创建另一个对象时Mvar 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
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go