標識符:編程
首先,在討論這三種東西以前,詳細說明一下C語言中的標識符。函數
標識符是用戶編程爲變量、常量、函數、語句等指定的名字,就比如人名同樣的東西。spa
標識符的命名規則以下:遞歸
1.只能由字母、數字、下劃線組成,而且首字符不能是數字;內存
2.不能把C語言的關鍵字做爲標識符;作用域
3.對大小寫敏感;原型
其次,須要明確,做用域和連接屬性是在標識符範疇內討論的,存儲類型是在標識符中的變量範疇內討論的。編譯器
做用域:編譯
標識符的做用域就是程序中該標識符能夠被使用的區域,由它的聲明位置決定。test
分爲如下四類:
1.文件做用域 2.代碼塊做用域 3.原型做用域 4.函數做用域
1.文件做用域:
任何在全部代碼塊以外聲明的標識符(變量、常量、函數名、語句等)具備,這表示這個標識符從它聲明的位置到這個源文件結尾處均可以訪問。
注意:在任何代碼塊以外聲明的函數名也具備文件做用域,由於這個函數名自己並不屬於任何代碼塊。
2.代碼塊做用域:
位於{}之間的全部語句稱爲代碼塊,在代碼塊內聲明的標識符,其做用域爲從其聲明位置開始到這段代碼塊結束,它能夠被這個區間內的語句訪問。
注意:處於嵌套狀態的代碼塊,當內層和層聲明瞭相同的標識符時,外層這個標識符在內層再也不起做用。編程中應該儘可能避免出現這種狀況。
3.原型做用域:
只適用於在函數原型中聲明的參數名,做用域爲函數原型中的()內,爲防止在同一個原型中不止一次使用這個名字。
4.函數做用域:
只用於語句標籤。
下面用一個例子說明幾種做用域:
#include
int a; //a具備文件做用域
void test(int *b); //b具備原型做用域
int main(void)
{
int c=10; //c具備代碼塊做用域
a=20;
printf("a=%d",a);
printf("Before change: c=%d",c);
test(&c);
printf("After change: c=%d",c);
for(int d=0;d<5;d++) //d具備代碼塊做用域
{
int e=0; //e僅在循環內起做用
printf("d=%d",d);
}
return 0;
}
void test(int *f) //f具備代碼塊做用域,在函數聲明中起做用
{
*f=30;
}
連接屬性:
做用域考慮的是單一源文件的狀況,而連接屬性是在多源文件範疇內的。連接屬性決定如何處理在不一樣源文件中出現的相同標識符。
分爲三種:
1.external(外部) 2.internal(內部) 3.none(無)
1.external:不管標識符聲明多少次,位於幾個源文件內,都表示同一實體;
2.internal:在同一源文件內的全部聲明屬於同一實體,不一樣源文件中的多個聲明則表示不一樣實體;
3.none:老是被當作單獨的個體,即不一樣的實體。
注意:
①缺省狀況下,具備文件做用域的變量、函數名的連接屬性爲external,其餘爲none;
用於修改標識符連接屬性的關鍵字:
1.static 2.extern
1.static:用於將external改成internal,若是被修改的標識符不是external,則起不到修改連接屬性的做用;
2.extern:
①對於具備文件做用域的標識符,extern加不加均可以;
②當extern再是第一次用於聲明標識符,那麼它的做用是表示變量或者函數的定義在別的文件中,提示編譯器遇到此變量和函數時在其餘模塊中尋找其定義;
③具備extern連接屬性的實體老是具備靜態存儲類型。
存儲類型:
指存儲變量值的內存類型,它決定變量的生存期。通常變量的存儲類型取決於聲明的位置。
分爲三種:
1.靜態(static)變量:在任何代碼塊以外聲明的變量,存儲於靜態內存中,在程序運行以前建立,並在程序執行期間始終存在;
2.自動(automatic)變量:在代碼塊內部聲明的變量默認爲自動變量,存儲於堆棧中,當程序執行代碼塊時才被建立,代碼塊執行結束時自動銷燬;
默認爲自動變量的緣由:
①當須要時再分配內存,減小內存的總需求量;
②有效實現遞歸。
3.寄存器(register)變量:用於聲明存儲於寄存器中的自動變量;將使用頻率較高的變量放入硬件寄存器,能夠提升效率。
關於static的兩點說明:
1.當static用來修飾函數定義、代碼塊以外的變量聲明時,用於修改其連接屬性,從external->internal,不改變做用域和存儲類型(有表示「本地」之意);
2.看成用於代碼塊內部的變量聲明時,用於修改變量的存儲類型,從auto->static,不改變做用域和連接屬性。