“語(yǔ)言的作用域規(guī)則”是一組確定一部分代碼是否“可見(jiàn)”或可訪問(wèn)另一部分代碼和數(shù)據(jù)的規(guī)則。
C語(yǔ)言中的每一個(gè)函數(shù)都是一個(gè)獨(dú)立的代碼塊。一個(gè)函數(shù)的代碼塊是隱藏于函數(shù)內(nèi)部的,不能被任何其它函數(shù)中的任何語(yǔ)句(除調(diào)用它的語(yǔ)句之外)所訪問(wèn)(例如,用g o t o語(yǔ)句跳轉(zhuǎn)到另一個(gè)函數(shù)內(nèi)部是不可能的)。構(gòu)成一個(gè)函數(shù)體的代碼對(duì)程序的其它部分來(lái)說(shuō)是隱蔽的,它既不能影響程序其它部分,也不受其它部分的影響。換言之,由于兩個(gè)函數(shù)有不同的作用域,定義在一個(gè)函數(shù)內(nèi)部的代碼數(shù)據(jù)無(wú)法與定義在另一個(gè)函數(shù)內(nèi)部的代碼和數(shù)據(jù)相互作用。
C語(yǔ)言中所有的函數(shù)都處于同一作用域級(jí)別上。這就是說(shuō),把一個(gè)函數(shù)定義于另一個(gè)函數(shù)內(nèi)部是不可能的。
4.2.1 局部變量
在函數(shù)內(nèi)部定義的變量成為局部變量。在某些C語(yǔ)言教材中,局部變量稱為自動(dòng)變量,這就與使用可選關(guān)鍵字a u t o定義局部變量這一作法保持一致。局部變量?jī)H由其被定義的模塊內(nèi)部的語(yǔ)句所訪問(wèn)。換言之,局部變量在自己的代碼模塊之外是不可知的。切記:模塊以左花
括號(hào)開(kāi)始,以右花括號(hào)結(jié)束。
對(duì)于局部變量,要了解的最重要的東西是:它們僅存在于被定義的當(dāng)前執(zhí)行代碼塊中,即局部變量在進(jìn)入模塊時(shí)生成,在退出模塊時(shí)消亡。
定義局部變量的最常見(jiàn)的代碼塊是函數(shù)。例如,考慮下面兩個(gè)函數(shù)。
整數(shù)變量x被定義了兩次,一次在func1()中,一次在func2()中。func1()和func2()中的x互不相關(guān)。其原因是每個(gè)x作為局部變量?jī)H在被定義的塊內(nèi)可知。
語(yǔ)言中包括了關(guān)鍵字auto,它可用于定義局部變量。但自從所有的非全局變量的缺省值假定為auto以來(lái),auto就幾乎很少使用了,因此在本書(shū)所有的例子中,均見(jiàn)不到這一關(guān)鍵字。
在每一函數(shù)模塊內(nèi)的開(kāi)始處定義所有需要的變量,是最常見(jiàn)的作法。這樣做使得任何人讀此函數(shù)時(shí)都很容易,了解用到的變量。但并非必須這樣做不可,因?yàn)榫植孔兞靠梢栽谌魏文K中定義。為了解其工作原理,請(qǐng)看下面函數(shù)。
這里的局部變量s就是在if塊入口處建立,并在其出口處消亡的。因此s僅在if塊中可知,而在其它地方均不可訪問(wèn),甚至在包含它的函數(shù)內(nèi)部的其它部分也不行。
在一個(gè)條件塊內(nèi)定義局部變量的主要優(yōu)點(diǎn)是僅在需要時(shí)才為之分配內(nèi)存。這是因?yàn)榫植孔兞績(jī)H在控制轉(zhuǎn)到它們被定義的塊內(nèi)時(shí)才進(jìn)入生存期。雖然大多數(shù)情況下這并不十分重要,但當(dāng)代碼用于專用控制器(如識(shí)別數(shù)字安全碼的車庫(kù)門(mén)控制器)時(shí),這就變得十分重要了,因?yàn)檫@時(shí)隨機(jī)存儲(chǔ)器(RAM)極其短缺。
由于局部變量隨著它們被定義的模塊的進(jìn)出口而建立或釋放,它們存儲(chǔ)的信息在塊工作結(jié)束后也就丟失了。切記,這點(diǎn)對(duì)有關(guān)函數(shù)的訪問(wèn)特別重要。當(dāng)訪問(wèn)一函數(shù)時(shí),它的局部變量被建立,當(dāng)函數(shù)返回時(shí),局部變量被銷毀。這就是說(shuō),局部變量的值不能在兩次調(diào)用之間保持。
4.2.2全局變量
與局部變量不同,全局變量貫穿整個(gè)程序,并且可被任何一個(gè)模塊使用。它們?cè)谡麄€(gè)程序執(zhí)行期間保持有效。全局變量定義在所有函數(shù)之外,可由函數(shù)內(nèi)的任何表達(dá)式訪問(wèn)。在下面的程序中可以看到,變量count定義在所有函數(shù)之外,函數(shù)main()之前。但其實(shí)它可以放置在任何第一次被使用之前的地方,只要不在函數(shù)內(nèi)就可以。實(shí)踐表明,定義全局變量的最佳位置是在程序的頂部。
仔細(xì)研究此程序后,可見(jiàn)變量count既不是main()也不是func1()定義的,但兩者都可以使用它。函數(shù)func2()也定義了一個(gè)局部變量count。當(dāng)func2訪問(wèn)count時(shí),它僅訪問(wèn)自己定義的局部變量count,而不是那個(gè)全局變量count。切記,全局變量和某一函數(shù)的局部變量同名時(shí),該函數(shù)對(duì)該名的所有訪問(wèn)僅針對(duì)局部變量,對(duì)全局變量無(wú)影響,這是很方便的。然而,如果忘記了這點(diǎn),即使程序看起來(lái)是正確的,也可能導(dǎo)致運(yùn)行時(shí)的奇異行為。
全局變量由C編譯程序在動(dòng)態(tài)區(qū)之外的固定存儲(chǔ)區(qū)域中存儲(chǔ)。當(dāng)程序中多個(gè)函數(shù)都使用同一數(shù)據(jù)時(shí),全局變量將是很有效的。然而,由于三種原因,應(yīng)避免使用不必要的全局變量:
①不論是否需要,它們?cè)谡麄€(gè)程序執(zhí)行期間均占有存儲(chǔ)空間。②由于全局變量必須依靠外部定義,所以在使用局部變量就可以達(dá)到其功能時(shí)使用了全局變量,將降低函數(shù)的通用性,這是因?yàn)樗蕾嚻浔旧碇獾臇|西。③大量使用全局變量時(shí),不可知的和不需要的副作用將
可能導(dǎo)致程序錯(cuò)誤。如在編制大型程序時(shí)有一個(gè)重要的問(wèn)題:變量值都有可能在程序其它地點(diǎn)偶然改變。
結(jié)構(gòu)化語(yǔ)言的原則之一是代碼和數(shù)據(jù)的分離。C語(yǔ)言是通過(guò)局部變量和函數(shù)的使用來(lái)實(shí)現(xiàn)這一分離的。下面用兩種方法編制計(jì)算兩個(gè)整數(shù)乘積的簡(jiǎn)單函數(shù)mul()。
通用的專用的
mul(x,y) intx,y;
intx,y; mul()
{{
return(x*y);return(x*y);
}}
兩個(gè)函數(shù)都是返回變量x和y的積,可通用的或稱為參數(shù)化版本可用于任意兩整數(shù)之積,而專用的版本僅能計(jì)算全局變量x和y的乘積。
4.2.3動(dòng)態(tài)存儲(chǔ)變量
從變量的作用域原則出發(fā),我們可以將變量分為全局變量和局部變量;換一個(gè)方式,從變量的生存期來(lái)分,可將變量分為動(dòng)態(tài)存儲(chǔ)變量及靜態(tài)存儲(chǔ)變量。
動(dòng)態(tài)存儲(chǔ)變量可以是函數(shù)的形式參數(shù)、局部變量、函數(shù)調(diào)用時(shí)的現(xiàn)場(chǎng)保護(hù)和返回地址。
這些動(dòng)態(tài)存儲(chǔ)變量在函數(shù)調(diào)用時(shí)分配存儲(chǔ)空間,函數(shù)結(jié)束時(shí)釋放存儲(chǔ)空間。動(dòng)態(tài)存儲(chǔ)變量的定義形式為在變量定義的前面加上關(guān)鍵字“auto”,例如:
auto int a,b,c;
“auto”也可以省略不寫(xiě)。事實(shí)上,我們已經(jīng)使用的變量均為省略了關(guān)鍵字“auto”的動(dòng)態(tài)存儲(chǔ)變量。有時(shí)我們甚至為了提高速度,將局部的動(dòng)態(tài)存儲(chǔ)變量定義為寄存器型的變量,定義的形式為在變量的前面加關(guān)鍵字“register”,例如:
register int x,y,z;
這樣一來(lái)的好處是:將變量的值無(wú)需存入內(nèi)存,而只需保存在CPU內(nèi)的寄存器中,以使速度大大提高。由于CPU內(nèi)的寄存器數(shù)量是有限的,不可能為某個(gè)變量長(zhǎng)期占用。因此,一些操作系統(tǒng)對(duì)寄存器的使用做了數(shù)量的限制?;蚨嗷蛏伲蚋静惶峁?,用自動(dòng)變量來(lái)替代。
4.2.4靜態(tài)存儲(chǔ)變量
在編譯時(shí)分配存儲(chǔ)空間的變量稱為靜態(tài)存儲(chǔ)變量,其定義形式為在變量定義的前面加上關(guān)鍵字“static”,例如:
static int a=8;
定義的靜態(tài)存儲(chǔ)變量無(wú)論是做全程量或是局部變量,其定義和初始化在程序編譯時(shí)進(jìn)行。
作為局部變量,調(diào)用函數(shù)結(jié)束時(shí),靜態(tài)存儲(chǔ)變量不消失并且保留原值。
從上述程序看,函數(shù)f()被三次調(diào)用,由于局部變量x是靜態(tài)存儲(chǔ)變量,它是在編譯時(shí)分配存儲(chǔ)空間,故每次調(diào)用函數(shù)f()時(shí),變量x不再重新初始化,保留加1后的值,得到上面的輸出。
C語(yǔ)言函數(shù)的作用域規(guī)則
相關(guān)推薦
- 2025年國(guó)外gpu服務(wù)器多少錢(qián)一臺(tái)?
- 跨境電商必看:主域名和子域名的區(qū)別
- 華納云618大促,166元買8H16G5M香港cn2云服務(wù)器,大帶寬服務(wù)器688起
- RAKsmart防護(hù)配置實(shí)戰(zhàn):10Gbps套餐部署指南
- 如何利用RAKsmart服務(wù)器實(shí)現(xiàn)高效多站點(diǎn)部署方案
- 華納云香港高防服務(wù)器150G防御4.6折促銷,低至6888元/月,CN2大帶寬直連清洗,終身循環(huán)折扣
- RakSmart服務(wù)器成本優(yōu)化策略
- 自媒體推廣實(shí)時(shí)監(jiān)控從服務(wù)器帶寬到用戶行為解決方法