所謂的作用域就是指變量起作用的范圍,也是變量的有效范圍。變量按他的作用域可以分為局部變量和全局變量。
在一個(gè)函數(shù)內(nèi)部聲明的變量是內(nèi)部變量,它只在本函數(shù)內(nèi)有效,在本函數(shù)以外是不能使用的,這樣的變量就是局部變量。此外,函數(shù)的形參也是局部變量,形參我們會(huì)在后面再詳細(xì)解釋。
比如上節(jié)課程序中定義的 unsigned long sec 這個(gè)變量,它是定義在 main 函數(shù)內(nèi)部的,所以只能由 main 函數(shù)使用,中斷函數(shù)就不能使用這個(gè)變量。同理,我們?nèi)绻谥袛嗪瘮?shù)內(nèi)部定義的變量,在 main 函數(shù)中也是不能使用的。
在函數(shù)外聲明的變量就是全局變量。一個(gè)源程序文件可以包含一個(gè)或者多個(gè)函數(shù),全局變量的作用范圍是從它開始聲明的位置一直到程序結(jié)束。
比如上節(jié)課程序中定義的 unsigned char LedBuff[6]這個(gè)數(shù)組,它的作用域就是從開始定義的位置一直到程序結(jié)束,不管是 main 函數(shù),還是中斷函數(shù) InterruptTimer0,都可以直接使用這個(gè)數(shù)組。
局部變量只有在聲明它的函數(shù)范圍內(nèi)可以使用,而全局變量可以被作用域內(nèi)的所有的函數(shù)直接使用。所以在一個(gè)函數(shù)內(nèi)既可以使用本函數(shù)內(nèi)聲明的局部變量,也可以使用全局變量。
從編程規(guī)范上講,一個(gè)程序文件內(nèi)所有的全局變量都應(yīng)定義在文件的開頭部分,在文件中所有函數(shù)之前。
由于 C 語言函數(shù)只有一個(gè)返回值,但是我們卻經(jīng)常會(huì)希望一個(gè)函數(shù)可以提供或影響多個(gè)結(jié)果值,這時(shí)我們就可以利用全局變量來實(shí)現(xiàn)。但是考慮到全局變量的一些特征,應(yīng)該限制全局變量的使用,過多使用全局變量也會(huì)帶來一些問題。
1) 全局變量可以被作用域內(nèi)所有的函數(shù)直接引用,可以增加函數(shù)間數(shù)據(jù)聯(lián)系的途徑,但同時(shí)加強(qiáng)了函數(shù)模塊之間的數(shù)據(jù)聯(lián)系,使這些函數(shù)的獨(dú)立性降低,對(duì)其中任何一個(gè)函數(shù)的修改都可能會(huì)影響到其它函數(shù)的執(zhí)行結(jié)果,函數(shù)之間過于緊密的聯(lián)系不利于程序的維護(hù)的。
2) 全局變量的應(yīng)用會(huì)降低函數(shù)的通用性,函數(shù)在執(zhí)行的時(shí)候過多依賴于全局變量,不利于函數(shù)的重復(fù)利用。目前我們編寫的程序還都比較簡(jiǎn)單,就一個(gè) .c 文件,但以后我們要學(xué)到一個(gè)程序中有多個(gè) .c 文件,當(dāng)一個(gè)函數(shù)被另外一個(gè) .c 文件調(diào)用的時(shí)候,必須將這個(gè)全局變量的變量值一起移植,而全局變量不只被一個(gè)函數(shù)調(diào)用,這樣會(huì)引起一些不可預(yù)見的后果。
3) 過多使用全局變量會(huì)降低程序的清晰度,使程序的可讀性下降。在各個(gè)函數(shù)執(zhí)行的時(shí)候都可能改變?nèi)肿兞恐?,往往難以清楚的判斷出每個(gè)時(shí)刻各個(gè)全局變量的值。
4) 定義全局變量會(huì)永久占用單片機(jī)的內(nèi)存單元,而局部變量只有進(jìn)入定義局部變量的函數(shù)時(shí)才會(huì)占用內(nèi)存單元,函數(shù)退出后會(huì)自動(dòng)釋放所占用的內(nèi)存。所以大量的全局變量會(huì)額外增加內(nèi)存消耗。
綜上所述之原因,在編程規(guī)范上有一條原則,就是盡量減少全局變量的使用,能用局部變量代替的就不用全局變量。
還有一種特殊情況,大家在看別人程序的時(shí)候請(qǐng)注意,C 語言是允許局部變量和全局變量同名的,他們定義后在內(nèi)存中占有不同的內(nèi)存單元。如果在同一源文件中,全局變量和局部變量同名,在局部變量作用域范圍內(nèi),只有局部變量有效,全局變量不起作用,也就是說局部變量具有更高優(yōu)先級(jí)。但是從編程規(guī)范上講,是要避免全局變量與局部變量重名的,從而避免不必要的誤解和誤操作。