2.鏈接
一個(gè)C變量具有下列鏈接之一:
外部鏈接 (external linkage)
內(nèi)部鏈接 (internal linkage)
空鏈接 (no linkage)
具有代碼塊作用域或者函數(shù)原型作用域的變量具有空鏈接,意味著它們是由其定義所在的代碼塊或函數(shù)原型所私有的。
具有文件作用域的變量可能有內(nèi)部或者外部鏈接。
一個(gè)具有外部鏈接的變量可以在一個(gè)多文件程序的任何地方使用。
一個(gè)具有內(nèi)部鏈接的變量可以在一個(gè)文件的任何地方使用。
那怎樣知道一個(gè)文件作用域變量具有內(nèi)部鏈接還是外部鏈接?
你可以看看在外部定義中是否使用了存儲(chǔ)類說(shuō)明符static:
int giants = 5;//文件作用域,外部鏈接
static int dodgers = 3;//文件作用域,內(nèi)部鏈接
int main ()
{
……
}
和該文件屬于同一程序的其他文件可以使用變量giants。
變量dodgers是該文件私有的,但是可以被該文件中的任一函數(shù)使用。
2.存儲(chǔ)時(shí)期
一個(gè)C變量有兩種存儲(chǔ)時(shí)期之一:
靜態(tài)存儲(chǔ)時(shí)期(static storage duration)和自動(dòng)存儲(chǔ)時(shí)期(automatic storage duration)。
如果一個(gè)變量具有靜態(tài)存儲(chǔ)時(shí)期,它在程序執(zhí)行期間將一直存在。
具有文件作用域的變量具有靜態(tài)存儲(chǔ)時(shí)期。
注意對(duì)于具有文件作用域的變量,關(guān)鍵字static表示鏈接類型,并非存儲(chǔ)時(shí)期。
因?yàn)樗械奈募饔糜蜃兞浚瑹o(wú)論它具有內(nèi)部鏈接,還是具有外部鏈接,都具有靜態(tài)存儲(chǔ)時(shí)期。
具有代碼塊作用域的變量一般情況下具有自動(dòng)存儲(chǔ)時(shí)期。
當(dāng)程序進(jìn)入定義這些變量的代碼塊時(shí),將為這些變量分配內(nèi)存。
當(dāng)推出這個(gè)代碼塊時(shí),內(nèi)存將被釋放。
這樣,在一個(gè)函數(shù)調(diào)用結(jié)束后,它的變量所占用的內(nèi)存空間可以用來(lái)存儲(chǔ)下一個(gè)被調(diào)用函數(shù)的變量。
到現(xiàn)在我們所使用的局部變量都屬于自動(dòng)類型。
void bore (int number)
{
int index;
for (index = 0; index < number; index++)
{
puts ("They don't make them the way they used to.\n");
return 0;
}
}
總論:c使用作用域、鏈接和存儲(chǔ)時(shí)期來(lái)定義5中存儲(chǔ)類。
自動(dòng),寄存器、具有代碼塊作用域的靜態(tài)、具有外部鏈接的靜態(tài)、具有內(nèi)部鏈接的靜態(tài)
1.自動(dòng)變量
自動(dòng)變量具有自動(dòng)存儲(chǔ)時(shí)期、代碼塊作用域和空鏈接。
默認(rèn)情況下,在代碼塊或函數(shù)的頭部定義的任意變量都屬于自動(dòng)存儲(chǔ)類。
你可以顯示的使用關(guān)鍵字auto來(lái)表明一個(gè)變量為自動(dòng)變量,但我們一般不寫(xiě)。
int main (void)
{
auto int plox;
}
int loop (int n)
{
int m; // m的作用域
scanf ("%d", &m);
{
int i; // m和i的作用域
for (i=m; i < n; i++)
{
puts ("i is local to a sub-block\n");
}
}
return m; // m的作用域, i已經(jīng)消失
}
如果在內(nèi)層代碼塊定義了一個(gè)具有和外層代碼塊便來(lái)那個(gè)同一名字的變量,將會(huì)怎樣?
(最好不要在你的代碼中這樣做)
這時(shí)內(nèi)層代碼塊將使用在內(nèi)層代碼塊中這個(gè)新定義的變量。
我們稱之為內(nèi)層定義覆蓋(hide)了外部定義,只有當(dāng)運(yùn)行離開(kāi)內(nèi)層代碼塊是,外部變量才會(huì)重新恢復(fù)使用。
#include <stdio.h>
int main (void)
{
int x = 30;
printf ("x in outer block: %d\n", x);
{
int x = 77;
printf ("x in inner block: %d\n", x);
}
}
注意:
c99中規(guī)定,語(yǔ)句若為循環(huán)或者if語(yǔ)句的一部分,即使沒(méi)有使用{},也認(rèn)為是一個(gè)代碼塊。
#include <stdio.h>
int main (void)
{
int n = 10;
printf ("Initially, n = %d\n", n);
for (int n = 1; n < 3; n++)
printf ("loop : n = %d\n", n);
printf ("Initially, n = %d\n", n);
return 0;
}
注意:
除非您顯式地初始化自動(dòng)變量,否則它不會(huì)被自動(dòng)初始化。
int main (void)
{
int repid;
int tents = 5;
}
repid的初值則是先前占用分配給它的空間的任意值。不要指望這個(gè)值是0。
2.寄存器變量
通常,變量存儲(chǔ)在計(jì)算機(jī)內(nèi)存中。如果幸運(yùn),寄存器變量可以被存儲(chǔ)在CPU的寄存器中,這樣速度會(huì)更快。
在其它許多方面,它和自動(dòng)變量是一樣的。
通過(guò)使用存儲(chǔ)類型說(shuō)明符register可以聲明寄存器變量。
int main (void)
{
register int quick;
}
我們說(shuō)如果幸運(yùn)是因?yàn)槁暶饕粋€(gè)寄存器類變量?jī)H僅是一個(gè)請(qǐng)求,而不是一條直接命令。
因?yàn)镃PU寄存器往往很少,編譯器必須在可用寄存器的個(gè)數(shù)和可用高速內(nèi)存的數(shù)量之間做權(quán)衡。
這種情況下,變量成為一個(gè)普通的自動(dòng)變量。
但是,你不能對(duì)它使用地址運(yùn)算符。
可以把一個(gè)形式參量請(qǐng)求為寄存器變量。
void macho (register int n)
3.具有代碼塊作用域的靜態(tài)變量
靜態(tài)變量像是一個(gè)不可變的變量。
但實(shí)際上,靜態(tài)指變量的的位置固定不動(dòng)。
具有文件作用域的變量自動(dòng)的具有靜態(tài)存儲(chǔ)時(shí)期。
也可以創(chuàng)建具有代碼塊作用域,兼具有靜態(tài)存儲(chǔ)的局部變量。
這些變量和自動(dòng)變量具有相同的作用域,當(dāng)包含這些變量的函數(shù)完成工作時(shí),它們并不消失。
從一次函數(shù)調(diào)用到下一次調(diào)用,計(jì)算機(jī)都記錄著他們的值。
我們可以使用存儲(chǔ)類說(shuō)明符static在代碼塊內(nèi)聲明這些變量。
#include <stdio.h>
void trystat (void);
int main (void)
{
int count;
for (count = 1; count <= 3; count++)
{
printf ("Here comes iteration %d:\n", count);
trystat ();
}
return 0;
}
void trystat (void)
{
int fade = 1;
static int stay = 1;
printf ("fade = %d and stay = %d\n", fade++, stay++);
}
注意:
對(duì)函數(shù)參數(shù)不能使用static。
4.具有外部鏈接的靜態(tài)變量
具有外部鏈接的靜態(tài)變量具有文件作用域、外部鏈接和靜態(tài)存儲(chǔ)時(shí)期。
這一類型的變量成為外部變量 external variable。
把變量的定義聲明放在所有函數(shù)之外,即創(chuàng)建了一個(gè)外部變量。
為了使程序更加清晰,可以在使用外部變量的函數(shù)中通過(guò)使用extern關(guān)鍵字來(lái)再次聲明它。
如果變量是在別的文件中定義的,使用extern來(lái)聲明該變量就是必須的。
int Errupt; //外部定義的變量
double Up[100]; //外部聲明的數(shù)組
extern char Coal; //必須的聲明,因?yàn)镃oal在其它文件中定義
void next (void);
int main (void)
{
extern int Errupt;//可選的聲明
extern double Up[];//可選的聲明
}
void next (void)
{
}
注意:
不同于自動(dòng)變量,如果您不對(duì)外部變量進(jìn)行初始化,他們將自動(dòng)被賦初值0。
這一原則也適用于外部定義的數(shù)組。
5.具有內(nèi)部靜態(tài)鏈接的靜態(tài)變量
通過(guò)使用存儲(chǔ)類說(shuō)明符(注意不是靜態(tài)變量聲明符)static在所有函數(shù)的外部進(jìn)行定義,前面已經(jīng)說(shuō)過(guò)該變量為整個(gè)文件私有
,這里不再討論。
int traveler = 1; //外部鏈接
static int stayhome = 1; //內(nèi)部鏈接