1. 运行环境

go version go1.15.4 linux/amd64

2. 问题描述?

package main

import (
    "fmt"
)

func main() {
    b := new(map[int]string)
    fmt.Printf("b: %p\n", b)
    fmt.Printf("&b: %p\n", &b)

    c := make(map[int]string)
    fmt.Printf("c: %p\n", c)
    fmt.Printf("&c: %p\n", &c)
}
/*
打印结果
b: 0xc0000ba020
&b: 0xc0000ba018
c: 0xc000098150
&c: 0xc0000ba030
*/

上述代码中打印的b和&b,c和&c为什么不一样呢?
b和c是变量b和c的地址,那另外两个是什么地址,有什么特殊含义吗?

补充

func (p *pp) printArg(arg interface{}, verb rune) {
    ...
    switch verb {
    case  'T':
        p.fmt.fmtS(reflect.TypeOf(arg).String())
        return
    case  'p':
        p.fmtPointer(reflect.ValueOf(arg), 'p')
        return
    }
    ...
}
func (p *pp) fmtPointer(value reflect.Value, verb rune) {
    var u uintptr
    switch value.Kind() {
    case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
        u = value.Pointer()
    default:
        p.badVerb(verb)
        return
    }
    ...
}

上述是一段fmt.Printf在打印%p时候的一段源码,可以看出,当打印数据为符合类型,函数,指针的时候%p返回的就是当前值的指针,也就是上述打印的b和c即为变量指针。 这时候&b和&c也就成为了指向指针变量的指针地址。
疑问:程序在打印&b和&c这两行时是否真正的分配内存空间了呢?
观察到的现象:从多次执行结果看,b与&b的地址总相差2(16进制),c与&c却相差甚远。(可能跟make和new的源码有关系)

// new的源码返
func newobject(typ *_type) unsafe.Pointer

// makemap的源码
func makemap_small() *hmap
复合类型 变量地址