golang 中的切片地址

2020-11-23 16:05:28 +08:00
 Chaox

func main() {
    months := []string{1: "January"}
    fmt.Printf("%p,\n",&months)                //0xc0000ae040,
    fmt.Printf("%p,\n",months)                //0xc0000ae060,
    fmt.Printf("%p,\n",&months[0])           //0xc0000ae060,
}

我知道第二个和第三个打印函数指向的是底层数组的第一个元素的地址。 但是我想问的是第一个打印函数中打印的地址指向的是什么? 对切片这个引用类型(本身传递的就是地址)取地址会取到什么呢?

(我在 stackoverflow 上看到回答是指向 slice 的 header 。我的疑惑是这个 header 如果表示的是 slice 结构体,但是 slice 结构体的第一个成员变量就是数组的指针,那么结构体的地址不就是第一个成员变量的地址吗,不就是底层数组的第一个元素吗?)

2077 次点击
所在节点    Go 编程语言
8 条回复
johnkiller
2020-11-23 17:04:39 +08:00
months 是一个指针变量,存一个地址,指向这个切片。

这个指针变量同样需要一个内存地址来存储。

int *p;

int a = 5;

p = &a;

p 存了 a 的地址,但 p 本身也需要一个内存地址来存储。

把 p 理解成一个 cpu 字长大小的整形变量,他存了一个整形地址。所以它也需要一个内存地址。

个人理解,如果有错感谢指正。
lujjjh
2020-11-23 17:15:27 +08:00
fmt.Printf("0x%x\n", (*reflect.SliceHeader)(unsafe.Pointer(&months)).Data)
hellos
2020-11-23 17:15:39 +08:00
第一个是指针自己的地址
icexin
2020-11-23 17:18:39 +08:00
func main() {
months := []string{1: "January"}
fmt.Printf("%p,\n", &months)
fmt.Printf("%p,\n", months)
fmt.Printf("%p,\n", &months[0])

header := (*reflect.SliceHeader)(unsafe.Pointer(&months))
fmt.Printf("%p,\n", header)
fmt.Printf("0x%x,\n", header.Data)
fmt.Printf("0x%x,\n", header.Data+0)
}

把你的代码翻译了一下,前面的几个打印语句等价于后面的三行
whoami9894
2020-11-23 19:48:24 +08:00
第一行打印 months 变量地址 (SliceHeader)
第二行从 months 变量地址处取一个指针变量的长度当做指针打印 (SliceHeader 开头也正好是 uintptr)
第三行打印 slice 指向的底层数组第一个元素地址
Chaox
2020-11-24 11:03:43 +08:00
@johnkiller 谢谢,理解了
Chaox
2020-11-24 11:03:55 +08:00
@icexin 谢谢,明白了
sunshinev
2020-11-27 17:58:38 +08:00
指针,和指针的指针

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/728365

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX