一.作用域
當變量被定義在程序不同位置時,它的作用范圍是不一樣的,這個作用范圍就是我們所說的作用域。
C語言編譯器可以確認4種不同類型的作用域:
——代碼塊作用域
——文件作用域
——原型作用域
——函數作用域
1.代碼塊作用域
在代碼塊中定義的變量,具有代碼塊作用域。作用范圍是從變量定義的位置開始,到標志該代碼塊結束的右大括號{}處
盡管函數的形式參數不在大括號內定義,但同樣具有代碼塊作用域,隸屬於包含函數體的代碼塊
#include <stdio.h> int main(void) { int i = 100; // i1 { int i = 110; // i2 { int i = 120; // i3 printf("i = %d\n", i); } // i = 110 { printf("i = %d\n", i); int i = 130; // i4 printf("i = %d\n", i); } printf("i = %d\n", i); } printf("i = %d\n", i); return 0; }
2.文件作用域
任何在代碼塊之外聲明的標識符都具有文件作用域,作用范圍是從它們的聲明位置開始,到文件的結尾處都是可以訪問的。
另外,函數名也具有文件作用域,因為函數名本身也是在代碼塊之外。
#include <stdio.h> void func(void); int main(void) { extern int count; func(); count++; printf("In main, count = %d\n", count); return 0; } int count; void func(void) { count++; printf("In func, count = %d\n", count); }
3.原型作用域
原型作用域只適用於那些在函數原型中聲明的參數名。函數在聲明的時候可以不寫參數的名字(但參數類型是必須是寫上的),其實函數原型的參數名還可以隨便寫一個名字,不必與形式參數相匹配。
void func(int a,int b,int c); void func(int d,int e, int f) { .... }
4.函數作用域
函數作用域只適用於goto語句的標簽,作用將goto語句的標簽限制在同一個函數內部,以及防止出現重名標簽
二.定義和聲明
當一個變量被定義的時候,編譯器為變量申請內存空間並填充一些值。
當一個變量被聲明的時候,編譯器就知道該變量被定義在其他地方。
聲明是通知編譯器該變量名及相關的類型已存在,不需要再為此申請內存空間。
局部變量既是定義又是聲明。
定義只能來一次,否則就叫做重復定義某個同名變量;而聲明可以有很多次。
三.鏈接屬性
1.external(外部的)
多個文件中聲明的同名標識符表示同一個實體
internal(內部的)
單個文件中聲明的同名標識符表示同一個實體
none(無)
聲明的同名標識符被當作獨立不同的實體
鏈接屬性只能修改一次,也就是說一旦將標識符的鏈接屬性變為internal,就無法變回external了
編譯器工作原理:https://fishc.com.cn/forum.php?mod=viewthread&tid=78063&extra=page%3D1%26filter%3Dtypeid%26typeid%3D571