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 结构体的第一个成员变量就是数组的指针,那么结构体的地址不就是第一个成员变量的地址吗,不就是底层数组的第一个元素吗?)
1
johnkiller 2020-11-23 17:04:39 +08:00
months 是一个指针变量,存一个地址,指向这个切片。
这个指针变量同样需要一个内存地址来存储。 int *p; int a = 5; p = &a; p 存了 a 的地址,但 p 本身也需要一个内存地址来存储。 把 p 理解成一个 cpu 字长大小的整形变量,他存了一个整形地址。所以它也需要一个内存地址。 个人理解,如果有错感谢指正。 |
2
lujjjh 2020-11-23 17:15:27 +08:00
fmt.Printf("0x%x\n", (*reflect.SliceHeader)(unsafe.Pointer(&months)).Data)
|
3
hellos 2020-11-23 17:15:39 +08:00
第一个是指针自己的地址
|
4
icexin 2020-11-23 17:18:39 +08:00 2
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) } 把你的代码翻译了一下,前面的几个打印语句等价于后面的三行 |
5
whoami9894 2020-11-23 19:48:24 +08:00
第一行打印 months 变量地址 (SliceHeader)
第二行从 months 变量地址处取一个指针变量的长度当做指针打印 (SliceHeader 开头也正好是 uintptr) 第三行打印 slice 指向的底层数组第一个元素地址 |
6
Chaox OP @johnkiller 谢谢,理解了
|
8
sunshinev 2020-11-27 17:58:38 +08:00
指针,和指针的指针
|