go內(nèi)存地址
- 內(nèi)存地址
在go中獲得該變量的內(nèi)存地址 用&a
func main() {
a := 43
b := &a
fmt.Println("a - ", a)
fmt.Println("b - ", b)
}
首先聲明了一個int類型的變量a,它的值為0,然后又聲明了一個a的引用b,b只是a的一個別名而已,并沒有占用內(nèi)存空間。實際上他們是同一個同西,在內(nèi)存中占用同樣的一個存儲單元。
變量名是個什么東西 賦的值又是個什么東西
char a;
1 變量
用來標識(identify)一塊內(nèi)存區(qū)域,這塊區(qū)域的值一般是可以更改的,這就是它“變”的由來,但是我們可以通過使用如
const等一些修飾符號來限定這一內(nèi)存區(qū)域的操作特性(characteristic),即變量的操作特性。用const修飾的使變量不能更改
的就和常量一樣的變量叫做常變量。
2 變量名
是一個標識符(identifier),用來指代一塊內(nèi)存區(qū)域,即變量,使用變量使我們操作內(nèi)存以區(qū)域(area),以塊(block)為單位,
提高了方便性。
3 變量名不會出現(xiàn)在機器中
你的機器代碼中,是不會出現(xiàn)變量名的;變量名是給我們程序員操作內(nèi)存來使用的。
想想在匯編年代,沒有變量名,我們操作內(nèi)存,都是用地址來直接操作的,還要控制區(qū)域大小;當然匯編語言已經(jīng)有了簡·
單的變量。
4 賦值操作過程
對于編譯器,它會搜集我們的變量名,比如我們定義了一個全局的int a;那么編譯器都為我們做了什么呢?
它會為程序預(yù)留4個字節(jié)的空間(假設(shè)在32位平臺),并把我們的變量名“a”保存進符號表,并用這個符號表的索引對應(yīng)實
際的空間
如果下面出現(xiàn)b = a;那么它就會根據(jù)符號表找到變量的真正的物理位置,取得它的值,賦給b。
這是寫編譯器需要做的,我們需要建立符號表。
但是實際在匯編層次上,操作的都是地址而已,不存在任何名稱了。
1、a 表示一塊內(nèi)存空間 表示本身的值
2、&a 表示當前內(nèi)存空間的地址 值所對應(yīng)的地址
那么指針變量就具有3種形態(tài):
1、a 表示指針a對應(yīng)的內(nèi)存空間(可以說就是指針本身的值)
2、&a 表示當前指針對應(yīng)的內(nèi)存空間的首地址(存放指針的地址) 指針就是一個地址
3、*a 表示指針a所指向的變量對應(yīng)的整個內(nèi)存空間。(指針指向的空間)指針變量 普通變量 內(nèi)存 和地址的全面對比
1 內(nèi)存
是什么,內(nèi)存是實實在在的硬件,可以存數(shù)據(jù),運行時的數(shù)據(jù)全放在里面
想想一點,內(nèi)存就像一個個的小個子,每個格子的帶下是一個一個字節(jié),可以存放一個字節(jié)的數(shù)據(jù)
2 地址
地址是內(nèi)訓(xùn)的一個表標識,每一個地址度對應(yīng)一個內(nèi)訓(xùn),所以內(nèi)存和地址一一對相應(yīng)
3 普通變量
如 char a; 就是一個普通變量。普通變量a其實是語言本身創(chuàng)造了,是為了更方便的表示內(nèi)存。我們對a進行訪問其實就
是直接對內(nèi)存進行訪問。至于a表示的內(nèi)存的地址是多少,程序員一般不用關(guān)心。編譯器會自動分配地址,也就是常說的
為a分配一個地址。如果想知道a的地址也可以通過&a得知。
4 指針變量
他和普通變量的區(qū)別在于,普通變量是和一塊內(nèi)存空間關(guān)聯(lián)。而指針變量卻是和兩塊內(nèi)存空間想關(guān)聯(lián):
5 go中所有的都是按值傳遞,對于復(fù)雜類型,傳的是指針的拷貝
func main() {
var m map[int]string = map[int]string{
0: "0",
1: "1",
}
mm := m
fmt.Printf("%p\n", &m) //0xc42002a028
fmt.Printf("%p\n", &mm) //0xc42002a030
fmt.Println(m) // map[0:0 1:1]
fmt.Println(mm) //map[1:1 0:0]
changeMap(m)
fmt.Printf("%p\n", &m) //0xc42002a028
fmt.Printf("%p\n", &mm) //0xc42002a030
fmt.Println(m) //map[2:2 0:0 1:1]
fmt.Println(mm) //map[0:0 1:1 2:2]
}
func changeMap(mmm map[int]string) {
mmm[2] = "2"
fmt.Printf("changeMap func %p\n", mmm) //changeMap func 0xc420014150
}
直接傳指針 也是傳指針的拷貝
func main() {
var m map[int]string = map[int]string{
0: "0",
1: "1",
}
mm := m
fmt.Printf("%p\n", &m) //0xc42002a028
fmt.Printf("%p\n", &mm) //0xc42002a030
fmt.Println(m) // map[0:0 1:1]
fmt.Println(mm) //map[1:1 0:0]
changeMap(&mm)
fmt.Printf("%p\n", &m) //0xc42002a028
fmt.Printf("%p\n", &mm) //0xc42002a030
fmt.Println(m) //map[2:2 0:0 1:1]
fmt.Println(mm) //map[0:0 1:1 2:2]
}
func changeMap(mmm *map[int]string) {
mmm = nil
fmt.Printf("changeMap func %p\n", mmm) //changeMap func 0xc420014150
}