程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C語言函數的作用域規則

C語言函數的作用域規則

編輯:關於C語言

“語言的作用域規則”是一組確定一部分代碼是否“可見”或可訪問另一部分代碼和數據的規則。

C語言中的每一個函數都是一個獨立的代碼塊。一個函數的代碼塊是隱藏於函數內部的,不能被任何其它函數中的任何語句(除調用它的語句之外)所訪問(例如,用g o t o語句跳轉到另一個函數內部是不可能的)。構成一個函數體的代碼對程序的其它部分來說是隱蔽的,它既不能影響程序其它部分,也不受其它部分的影響。換言之,由於兩個函數有不同的作用域,定義在一個函數內部的代碼數據無法與定義在另一個函數內部的代碼和數據相互作用。

C語言中所有的函數都處於同一作用域級別上。這就是說,把一個函數定義於另一個函數內部是不可能的。

4.2.1 局部變量

在函數內部定義的變量成為局部變量。在某些C語言教材中,局部變量稱為自動變量,這就與使用可選關鍵字a u t o定義局部變量這一作法保持一致。局部變量僅由其被定義的模塊內部的語句所訪問。換言之,局部變量在自己的代碼模塊之外是不可知的。切記:模塊以左花括號開始,以右花括號結束。

對於局部變量,要了解的最重要的東西是:它們僅存在於被定義的當前執行代碼塊中,即局部變量在進入模塊時生成,在退出模塊時消亡。

定義局部變量的最常見的代碼塊是函數。例如,考慮下面兩個函數。

整數變量x被定義了兩次,一次在func1()中,一次在func2()中。func1()和func2()中的x互不相關。其原因是每個x作為局部變量僅在被定義的塊內可知。

語言中包括了關鍵字auto,它可用於定義局部變量。但自從所有的非全局變量的缺省值假定為auto以來,auto就幾乎很少使用了,因此在本書所有的例子中,均見不到這一關鍵字。

在每一函數模塊內的開始處定義所有需要的變量,是最常見的作法。這樣做使得任何人讀此函數時都很容易,了解用到的變量。但並非必須這樣做不可,因為局部變量可以在任何模塊中定義。為了解其工作原理,請看下面函數。

這裡的局部變量s就是在if塊入口處建立,並在其出口處消亡的。因此s僅在if塊中可知,而在其它地方均不可訪問,甚至在包含它的函數內部的其它部分也不行。

在一個條件塊內定義局部變量的主要優點是僅在需要時才為之分配內存。這是因為局部變量僅在控制轉到它們被定義的塊內時才進入生存期。雖然大多數情況下這並不十分重要,但當代碼用於專用控制器(如識別數字安全碼的車庫門控制器)時,這就變得十分重要了,因為這時隨機存儲器(RAM)極其短缺。

由於局部變量隨著它們被定義的模塊的進出口而建立或釋放,它們存儲的信息在塊工作結束後也就丟失了。切記,這點對有關函數的訪問特別重要。當訪問一函數時,它的局部變量被建立,當函數返回時,局部變量被銷毀。這就是說,局部變量的值不能在兩次調用之間保持。

4.2.2全局變量

與局部變量不同,全局變量貫穿整個程序,並且可被任何一個模塊使用。它們在整個程序執行期間保持有效。全局變量定義在所有函數之外,可由函數內的任何表達式訪問。在下面的程序中可以看到,變量count定義在所有函數之外,函數main()之前。但其實它可以放置在任何第一次被使用之前的地方,只要不在函數內就可以。實踐表明,定義全局變量的最佳位置是在程序的頂部。

仔細研究此程序後,可見變量count既不是main()也不是func1()定義的,但兩者都可以使用它。函數func2()也定義了一個局部變量count。當func2訪問count時,它僅訪問自己定義的局部變量count,而不是那個全局變量count。切記,全局變量和某一函數的局部變量同名時,該函數對該名的所有訪問僅針對局部變量,對全局變量無影響,這是很方便的。然而,如果忘記了這點,即使程序看起來是正確的,也可能導致運行時的奇異行為。

全局變量由C編譯程序在動態區之外的固定存儲區域中存儲。當程序中多個函數都使用同一數據時,全局變量將是很有效的。然而,由於三種原因,應避免使用不必要的全局變量:

①不論是否需要,它們在整個程序執行期間均占有存儲空間。②由於全局變量必須依靠外部定義,所以在使用局部變量就可以達到其功能時使用了全局變量,將降低函數的通用性,這是因為它要依賴其本身之外的東西。③大量使用全局變量時,不可知的和不需要的副作用將可能導致程序錯誤。如在編制大型程序時有一個重要的問題:變量值都有可能在程序其它地點偶然改變。

結構化語言的原則之一是代碼和數據的分離。C語言是通過局部變量和函數的使用來實現這一分離的。下面用兩種方法編制計算兩個整數乘積的簡單函數mul()。
通用的專用的

mul(x,y) int x,y;
int x,y; mul()
{{
return (x*y);return (x*y);
}}
兩個函數都是返回變量x和y的積,可通用的或稱為參數化版本可用於任意兩整數之積,而專用的版本僅能計算全局變量x和y的乘積。

4.2.3動態存儲變量

從變量的作用域原則出發,我們可以將變量分為全局變量和局部變量;換一個方式,從變量的生存期來分,可將變量分為動態存儲變量及靜態存儲變量。

動態存儲變量可以是函數的形式參數、局部變量、函數調用時的現場保護和返回地址。

這些動態存儲變量在函數調用時分配存儲空間,函數結束時釋放存儲空間。動態存儲變量的定義形式為在變量定義的前面加上關鍵字“auto”,例如:

auto int a,b,c;

“auto”也可以省略不寫。事實上,我們已經使用的變量均為省略了關鍵字“auto”的動態存儲變量。有時我們甚至為了提高速度,將局部的動態存儲變量定義為寄存器型的變量,定義的形式為在變量的前面加關鍵字“register”,例如:

register int x,y,z;

這樣一來的好處是:將變量的值無需存入內存,而只需保存在CPU內的寄存器中,以使速度大大提高。由於CPU內的寄存器數量是有限的,不可能為某個變量長期占用。因此,一些操作系統對寄存器的使用做了數量的限制。或多或少,或根本不提供,用自動變量來替代。

4.2.4靜態存儲變量

在編譯時分配存儲空間的變量稱為靜態存儲變量,其定義形式為在變量定義的前面加上關鍵字“static”,例如:

static int a=8;

定義的靜態存儲變量無論是做全程量或是局部變量,其定義和初始化在程序編譯時進行。

作為局部變量,調用函數結束時,靜態存儲變量不消失並且保留原值。

從上述程序看,函數f()被三次調用,由於局部變量x是靜態存儲變量,它是在編譯時分配存儲空間,故每次調用函數f()時,變量x不再重新初始化,保留加1後的值,得到上面的輸出。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved