張家港高端網(wǎng)站制作百度總部公司地址在哪里
寫算法題的時候突然想到,為什么循環(huán)內(nèi)定義變量不會算作是重復(fù)定義,以及變量作用域問題,為此,進(jìn)行了一次探索
c:
代碼:
#include <stdio.h>
int main()
{int a = 0;int* b = &a;for (int i = 0; i < 3; i++) {printf("%d\n", a);printf("%p\n",&a);int a = i;printf("%d\n", a);printf("%p\n", &a);printf("------------------\n");}return 0;
}
運(yùn)行結(jié)果:
0
010FF91C
0
010FF8F8
------------------
0
010FF91C
1
010FF8F8
------------------
0
010FF91C
2
010FF8F8
------------------
java:
代碼:
public class Main{public static void main(String[]args) {int a = 1;for(int i = 0 ;i<2;i++){int a = i;System.out.println(a);System.out.println("---------------------");}}
}
java: 已在方法 main(java.lang.String[])中定義了變量 a
go:
代碼:
import "fmt"func main() {a := 0for i := 0; i < 3; i++ {fmt.Println(a)fmt.Println(&a)var a = ifmt.Println(a)fmt.Println(&a)fmt.Println("________________________")}
}
結(jié)果:
0
0xc00000a0b8
0
0xc00000a100
________________________
0
0xc00000a0b8
1
0xc00000a110
________________________
0
0xc00000a0b8
2
0xc00000a120
________________________
查閱資料得知,這個屬于是變量作用域的問題,局部變量如果超出作用域就會銷毀,正如C語言代碼運(yùn)行結(jié)果那樣,循環(huán)內(nèi)定義同一變量的地址值是不會改變的。
而且代碼在編譯時,會將重復(fù)定義的變量”提出“到循環(huán)外定義,也就是說,在循環(huán)內(nèi)定義和循環(huán)外定義在占用內(nèi)存上幾乎一樣
至于同名變量可以既在循環(huán)內(nèi)定義,又在循環(huán)外定義,這點(diǎn)還是跟作用域有關(guān),但為什么java不能這樣定義,emmm,沒有查到相關(guān)資料,知道的可以補(bǔ)充一下
還有個問題,那為什么go定義出來的變量地址不一樣呢?是沒有銷毀原來的局部變量嗎?這就要說到Go 有 escape analysis, 在編譯期,它會分析你的變量是否在函數(shù)執(zhí)行完畢那一刻,程序有沒有可能有別的對象引用到它(所謂逃逸),如果沒有,那這個變量就可以在棧上分配,完全不經(jīng)過 gc,如果它已經(jīng)逃逸了,那就不知道什么時候才能gc了~
這個代碼中的逃逸是由于fmt導(dǎo)致的,我們不妨不恰當(dāng)?shù)男薷囊幌麓a
import "fmt"func main() {a := 0for i := 0; i < 3; i++ {println(a)println(&a)var a = iprintln(a)println(&a)fmt.Println("________________________")}
}
結(jié)果:
0
0xc00006ff18
0
0xc00006ff10
________________________
0
0xc00006ff18
1
0xc00006ff10
________________________
0
0xc00006ff18
2
0xc00006ff10
________________________
可以看到,當(dāng)我們不使用標(biāo)準(zhǔn)輸出流,而是使用標(biāo)準(zhǔn)錯誤流打印的時候,可能就不會觸發(fā)逃逸,看到此時地址是一樣的,也就是印證了我們上面的結(jié)論。