在C語言中每個(gè)變量和函數(shù)都有其存儲(chǔ)屬性。存儲(chǔ)屬性關(guān)系到變量和函數(shù)的可見性與生存期,即變量和函數(shù)所占存儲(chǔ)位置的作用域和時(shí)限。
變量的可見性:指變量在其作用域內(nèi)是可以訪問的,或者說是變量的可見區(qū)域。變量的生存期:指在一定范圍內(nèi)變量值保存的時(shí)限。
由于變量的存儲(chǔ)屬性不同,有的變量可在程序的各個(gè)函數(shù)中使用,稱全局變量或全程變量;有的只能在特定函數(shù)中使用,稱局部變量;有些可為所屬文件中的函數(shù)使用,稱局部于文件函數(shù)的局部變量。
C語言的存儲(chǔ)屬性分為三類:自動(dòng)的、外部的和靜態(tài)的,其相應(yīng)的存儲(chǔ)類別說明符分別是:
auto自動(dòng)的
extern外部的
static靜態(tài)的
Franklin C51支持“基于存儲(chǔ)器的指針”和“一般指針”;诖鎯(chǔ)器的指針由C源程序中的存儲(chǔ)類型決定其存儲(chǔ)單元數(shù)。用這種指針可高效訪問對(duì)象,且只需1至2字節(jié)。而一般指針需要3字節(jié):2字節(jié)偏移和1字節(jié)存儲(chǔ)類型。指針的定義如表3所列。
例:
char xdata*px;指針自身在默認(rèn)存儲(chǔ)區(qū)(取決于存儲(chǔ)模式)
char xdata*data pdx;指針明確位于內(nèi)部數(shù)據(jù)存儲(chǔ)區(qū)(data)
data char xdata*pdx;與上同
表3
2. 動(dòng)態(tài)和靜態(tài)分配的變量
在C程序中,在一個(gè)函數(shù)中定義的自動(dòng)變量是動(dòng)態(tài)分配的變量。
自動(dòng)變量是:
-局部變量的一種;
-在一個(gè)函數(shù)中定義的變量;
-只能在其定義的函數(shù)內(nèi)部訪問。
當(dāng)調(diào)用一個(gè)函數(shù)時(shí),函數(shù)中的自動(dòng)變量在RAM或寄存器中分配存儲(chǔ)。當(dāng)一個(gè)函數(shù)執(zhí)行完時(shí),分配的RAM單元或寄存器釋放。因此,自動(dòng)變量?jī)H在定義它們的函數(shù)內(nèi)部可以訪問。
在C程序中,外部變量(在函數(shù)外用“extern”說明定義)和靜態(tài)變量(用“static”說明定義)是靜態(tài)分配的變量。
·外部變量(extern)
-在函數(shù)外部定義;
-在模塊中任何位置可以訪問;
-在存儲(chǔ)器中分配固定的存儲(chǔ)單元。
·靜態(tài)變量(static)
-只能在定義的有效范圍內(nèi)使用;
-在存儲(chǔ)器中分配固定的存儲(chǔ)單元。
變量的存儲(chǔ)空間是動(dòng)態(tài)分配還是靜態(tài)分配取決于它在程序中定義的位置。外部變量在函數(shù)外定義,在RAM中分配變量的存儲(chǔ)空間。由于變量的RAM單元已分配,因而,它可以在程序模塊中的任何地方訪問。
“static”定義的靜態(tài)變量雖然也在RAM中分配單元,但“靜態(tài)變量有效范圍”的存在,使得靜態(tài)變量的可見性取決于它在程序中定義的位置。在函數(shù)外定義的靜態(tài)變量稱作靜態(tài)全局變量,而在函數(shù)內(nèi)部定義的靜態(tài)變量稱作靜態(tài)局部變量。
靜態(tài)局部變量又稱內(nèi)部靜態(tài)變量。它在函數(shù)內(nèi)定義,但不像自動(dòng)變量那樣,當(dāng)函數(shù)調(diào)用它時(shí)就存在,退出函數(shù)它就消失。靜態(tài)變量始終存在著,但函數(shù)外部不能存取它,只能在函數(shù)內(nèi)部訪問,退出函數(shù)后,雖然數(shù)據(jù)仍保存,但不能訪問。
靜態(tài)全局變量又稱外部靜態(tài)變量。它在函數(shù)外面被定義,它的作用域從被定義的地方開始,一直到源文件結(jié)束。但一個(gè)程序由若干個(gè)文件組成時(shí),靜態(tài)全局變量始終存在著,但它只能在被定義的文件內(nèi)訪問,可供該文件內(nèi)的所有函數(shù)共享此數(shù)據(jù),退出文件后,雖然數(shù)據(jù)仍保存,但不能被其他文件訪問。
文件1:
init();
extern
int numproc;
int currid;
int semno;
int nextsem=0;
static int nextproc=100;
null()
{
int userpid=10;
init();
currid=userpid;
nextsem++;
semno=100-nextsem;
return(semno); }
init()
{
static int num=50;
int i=0;
int j;
return(num--);
}
文件2:
extern null();
extern int numproc;
extern int currid;
extern int semno;
extern int nextsem;
int numproc=100;
static int nextproc=50;
start()
{
int pid=0;
if(null()>0) pid++;
}
“num”是靜態(tài)局部變量,它分配的RAM單元僅有定義它的init()函數(shù)可以使用!皀extproc”是靜態(tài)全局變量,“nextproc”變量?jī)H在定義它的源程序文件中可見。另一個(gè)程序文件不能訪問到它分配的單元,因而,兩個(gè)“nextproc”變量分配不同的存儲(chǔ)單元。
綜上可知,靜態(tài)變量在定義它的函數(shù)或文件之外是不可訪問的、未知的,但它們?cè)诤瘮?shù)調(diào)用之間可以保存其值,這一特征使靜態(tài)變量很有用處,如用它編寫通用函數(shù)和庫函數(shù)時(shí),這些函數(shù)可被其他編程者使用。
(1) 自動(dòng)變量
自動(dòng)的存儲(chǔ)屬性是C語言中使用最廣泛的一類。按照缺省規(guī)則,在C語言程序中,每個(gè)函數(shù)的函數(shù)體所說明的變量,凡不加存儲(chǔ)屬性說明的,都表示為自動(dòng)存儲(chǔ)類別。當(dāng)然,對(duì)這些變量說明時(shí),也可以在前面綴以說明符auto,但習(xí)慣上通常都采用缺省形式,例如:
char c;
等價(jià)于
auto char c;
自動(dòng)變量的作用域,僅局限于定義該變量的函數(shù),因而是局部變量。其可見性與生命期和作用域相同。
自動(dòng)變量只在定義它的函數(shù)調(diào)用時(shí),系統(tǒng)才對(duì)它分配存儲(chǔ)空間,開始它的生命期;在從函數(shù)返回時(shí),它所占的存儲(chǔ)位置就自動(dòng)被抹除,從而結(jié)束它的生存期。因此,C語言將這種局部于函數(shù)的變量稱為自動(dòng)變量。
由于自動(dòng)變量隨函數(shù)的返回而消失,其存儲(chǔ)位置被抹除,故其值不能被保留。若程序下次再調(diào)用該函數(shù),雖然又對(duì)此自動(dòng)變量分配存儲(chǔ)空間,但它不會(huì)保留前次運(yùn)算得到的結(jié)果,故在函數(shù)體中必須給它進(jìn)行賦值。
因?yàn)樽詣?dòng)變量的可見性局限于定義它的函數(shù),對(duì)其他函數(shù)來說,它是不可見的,故其名可以被其他函數(shù)重復(fù)使用,它們各有自己的作用域,不會(huì)產(chǎn)生誤解,例如:
main()
{ int i,j,k;
…
}
fun()
{int i,j,k;
…
}
其中兩個(gè)函數(shù)main()和fun()都定義了變量i、j、k,雖然它們都是自動(dòng)變量,各自局限于定義它們的函數(shù),兩者之間沒有相關(guān)的聯(lián)系。
局部變量的概念可以擴(kuò)充到分程序,即對(duì)于分程序中的自動(dòng)變量,其作用域只局限于該程序內(nèi)。在分程序嵌套使用時(shí),若同名變量,其內(nèi)層變量的作用域也是局限于定義它的那個(gè)層次。
C編譯器總是嘗試在寄存器里保持局部變量。這樣,將索引變量(如for和while循環(huán)中計(jì)數(shù)變量)定義為局部變量是最好的。只要有可能,在函數(shù)中使用自動(dòng)變量。
(2) 外部變量
外部變量的存儲(chǔ)屬性說明符是extern。按照缺省規(guī)則,凡是在所有函數(shù)之前,在函數(shù)外面定義的變量都是外部變量,定義時(shí)可以不寫說明符extern,但在函數(shù)體內(nèi)定義外部變量時(shí),必須要用extern說明。
一個(gè)外部變量定義后,系統(tǒng)就給它分配固定的存儲(chǔ)空間,所有的函數(shù)和分程序都可以使用它。當(dāng)退出一個(gè)分程序,或從某一函數(shù)返回后,外部變量的空間并不回收,其值也仍然保留,可供其他函數(shù)所公用。故此,外部變量是全局變量。其作用域、可見性和生存期是整個(gè)程序。
C語言允許將大型程序分解為若干個(gè)獨(dú)立文件,分別進(jìn)行編譯,然后連接在一起,從而提高編譯速度,且便于管理。此時(shí),當(dāng)某變量需要在所有文件中通用時(shí),則只要在一個(gè)文件中說明其為全局變量,而在其他文件中用extern說明該變量就可以了。
例如,現(xiàn)有兩個(gè)文件File1和File2,它們都要用到3個(gè)變量i、j和ch,則在分別編譯的程序模塊中,對(duì)全局變量的說明如下:
File1
int i,j;
char ch;
main()
{
…
}
func11()
{
i=120;
…
}
File2
extern int i,j;
extern char ch;
func21()
{
…
i=j/10;
…
}
func22()
{
…
j=10;
…
}
其中,File2的extern通知編譯程序,它所定義的變量已在別的文件中說明,使編譯程序知其類型和名稱,而不用再為它們分配存儲(chǔ)空間。
(3) 靜態(tài)全局變量
在全局變量說明前加上static說明符就構(gòu)成靜態(tài)全局變量。它是一種作用域受限制的外部變量。其作用域是從說明處開始直至該文件的末尾,即它只在被定義的這個(gè)文件中是可見的。雖然它也是全局變量,但其他文件無法改變其內(nèi)容,從而可以避免其他文件可能引起的錯(cuò)誤。
源文件:
int timeint();
int time;
static int count=0;
int list()
{
int flag=0;
if(++count>=60)/* line 8 */
flag=timeint();
return(flag);
}
int timeint()
{
int temp;
if(!--temp){
time=10;
count-=60;/* line 18 */
}
temp=time*count;/* line 20 */
return(temp);
}
“count”變量在函數(shù)的外部定義是靜態(tài)全局變量!癱ount"變量在RAM中分配存儲(chǔ)單元保存它的值,可以在它編譯連接后生成的映像文件(.M51)中看到它分配的內(nèi)部RAM單元的地址,在列表文件(.LST)中可以看到其存儲(chǔ)單元的訪問和存儲(chǔ)器的使用情況。
映像文件:
D:000AH SYMBOL count
D:000CH PUBLIC time
D:0008H SYMBOL flag
D:0002H SYMBOL temp
“count”變量分配的內(nèi)部RAM單元的地址是0AH。
列表文件:
; SOURCE LINE # 8
0005 0500 R INC count+01H
0007 E500 R MOV A,count+01H
0009 7002 JNZ ?C0005
000B 0500 R INC count
000D ?C0005:
000D C3 CLR C
000E 943C SUBB A,#03CH
0010 E500 R MOV A,count
0012 6480 XRL A,#080H
0014 9480 SUBB A,#080H
0016 4007 JC ?C0001
; SOURCE LINE # 18
000E 74C4 MOV A,#0C4H
0010 2500 R ADD A,count+01H
0012 F500 R MOV count+01H,A
0014 74FF MOV A,#0FFH
0016 3500 R ADDC A,count
0018 F500 R MOV count,A
; SOURCE LINE # 20
001A AC00 R MOV R4,count
001C AD00 R MOV R5,count+01H
001E AE00 R MOV R6,time
0020 AF00 R MOV R7,time+01H
0022 120000E LCALL ?CIMUL
0025 AA06 MOV R2,AR6
0027 AB07 MOV R3,AR7
MODULE INFORMATION:STATIC OVERLAYABLE
CODE SIZE = 78 ---
CONSTANT SIZE = --- ---
XDATA SIZE = --- ---
PDATA SIZE = --- ---
DATA SIZE = 4 2
IDATA SIZE = --- ---
BIT SIZE = --- ---
END OF MODULE INFORMATION.
上面是和“count”變量有關(guān)源程序行對(duì)應(yīng)的匯編程序以及程序存儲(chǔ)器和數(shù)據(jù)存儲(chǔ)器的使用情況。(待續(xù))





