Go语言 同类型变量之间的地址间隔不同

fdbelqdn  于 2023-09-28  发布在  Go
关注(0)|答案(1)|浏览(99)

我注意到在某些版本的Go语言中,第一个和第二个int变量之间的差距有时会增加。

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    a := 7
    b := 8
    c := 9
    d := 10
    fmt.Printf("a's address is %v\n", &a)
    fmt.Printf("b's address is %v\n", &b)
    fmt.Printf("c's address is %v\n", &c)
    fmt.Printf("d's address is %v\n", &d)

    baSpan := uintptr(unsafe.Pointer(&b)) - uintptr(unsafe.Pointer(&a))
    cbSpan := uintptr(unsafe.Pointer(&c)) - uintptr(unsafe.Pointer(&b))
    dcSpan := uintptr(unsafe.Pointer(&d)) - uintptr(unsafe.Pointer(&c))

    // Go playground, Go 1.20 - Prints 8.
    // Go playground, Go dev branch - Sometimes prints 8, sometimes 24.
    // My machine, go1.20.4 windows/amd64 - Always prints 24.
    fmt.Printf("b-a span is %v\n", baSpan)

    fmt.Printf("c-b span is %v\n", cbSpan) // Prints 8
    fmt.Printf("d-c span is %v\n", dcSpan) // Prints 8
}

去操场,去1.20-https://go.dev/play/p/BJIVC1cQQoT
Go playground,Go dev - https://go.dev/play/p/BJIVC1cQQoT?v=gotip
这些问题是:
1.为什么打印24?剩下的16个字节是什么?* (考虑到a在64位机器上占用8个字节)*
1.为什么在围棋场上是随机的?
1.我们怎么知道其他16个字节是什么?我想这可以通过检查汇编代码来完成。还有其他办法吗?

5fjcxozz

5fjcxozz1#

堆分配依赖于实现和运行时。
x.go

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    a := 7
    b := 8
    c := 9
    d := 10
    fmt.Printf("a's address is %v\n", &a)
    fmt.Printf("b's address is %v\n", &b)
    fmt.Printf("c's address is %v\n", &c)
    fmt.Printf("d's address is %v\n", &d)

    baSpan := uintptr(unsafe.Pointer(&b)) - uintptr(unsafe.Pointer(&a))
    cbSpan := uintptr(unsafe.Pointer(&c)) - uintptr(unsafe.Pointer(&b))
    dcSpan := uintptr(unsafe.Pointer(&d)) - uintptr(unsafe.Pointer(&c))

    fmt.Printf("b-a span is %v\n", baSpan)
    fmt.Printf("c-b span is %v\n", cbSpan) 
    fmt.Printf("d-c span is %v\n", dcSpan) 
}
./x.go:9:2: moved to heap: a
./x.go:10:2: moved to heap: b
./x.go:11:2: moved to heap: c
./x.go:12:2: moved to heap: d
go1.20 version && go1.20 build -gcflags='-m' x.go && ./x
go version go1.20.7 linux/amd64
a's address is 0xc000018130
b's address is 0xc000018138
c's address is 0xc000018140
d's address is 0xc000018148
b-a span is 8
c-b span is 8
d-c span is 8
go1.21 version && go1.21 build -gcflags='-m' x.go && ./x
go version go1.21rc4 linux/amd64
a's address is 0xc00009c010
b's address is 0xc00009c018
c's address is 0xc00009c020
d's address is 0xc00009c028
b-a span is 8
c-b span is 8
d-c span is 8
go version && go build -gcflags='-m' x.go && ./x
go version devel go1.22-4e728e5121 Mon Aug 7 16:07:50 2023 +0000 X:loopvar linux/amd64
a's address is 0xc00009c010
b's address is 0xc00009c018
c's address is 0xc00009c020
d's address is 0xc00009c028
b-a span is 8
c-b span is 8
d-c span is 8

https://go.dev/play/p/HeAMYeBG1_o?v=go1.20

a's address is 0xc0000b2000
b's address is 0xc0000b2008
c's address is 0xc0000b2010
d's address is 0xc0000b2018
b-a span is 8
c-b span is 8
d-c span is 8

https://go.dev/play/p/HeAMYeBG1_o?v=gotip

a's address is 0xc000012028
b's address is 0xc000012040
c's address is 0xc000012048
d's address is 0xc000012050
b-a span is 24
c-b span is 8
d-c span is 8

相关问题