C 程序的外部變量與函數

C 程序的外部變量與函數

武漢市東湖中學
朱海清 孟學楨


摘要

 

本文討論了C程序的外部變量和函數的一些性質,結合實際的編程,給出了使用外部變量和函數的方法。

關鍵字:C程序,外部變量,函數

  C程序由一組對象組成,這些對象包括程序中所使用的變量和實現特定功能的函數。變量可以分爲函數內部定義、使用的變量和函數外部定義的變量,通常情況下,把函數內部定義、使用的變量稱爲內部變量或局部變量,而將在函數外部定義的、供許多函數所使用的變量稱爲外部變量,一般情況下,也可以稱爲全局變量。
  由於C語言不允許在一個函數中定義其他函數,因此函數本身是外部的。一般情況下,也可以說函數是全局函數。
在缺省情況下,外部變量與函數具有如下性質:所有通過名字對外部變量與函數的引用(即使這種引用來自獨立編譯的函數)都是引用的同一對象(標準中把這一性質稱爲外部連接)。
  由於外部變量是可以全局訪問的,這就爲在函數之間交換數據提供了一種可以替代函數變元欲返回值的方法。任何函數都可以用名字來訪問外部變量,只要這個名字已在某個地方做了說明或定義。
如果要在函數之間共享大量的變量,那麼使用外部變量要比使用一個長長的變元表更方便、有效。然而,也可能導致程序在各個函數之間產生太多的數據聯繫。
  外部變量的用途還表現在它們比內部變量有更大的作用域和更長的生存期。內部自動變量只能在函數內部使用,當其所在函數被調用時開始存在,當函數退出時消失。而外部變量是永久存在的,他們的值在從一次函數調用到下一次函數調用之間保持不變。因此,如果兩個函數必須共享某些數據,而這兩個函數都互不調用對方,那麼最爲方便的是,把這些共享數據作爲外部變量,而不是作爲變元來傳遞。

1、外部變量的定義和使用

  根據C語言標準,在程序的所有源文件中,外部變量只能被定義一次,否則會導致重複定義的編譯錯誤。

1.1 外部變量的定義與聲明

  變量聲明用於通報變量的性質(主要是變量的類型),而變量定義則除此之外還引起存儲分配。如果在函數的外部包含如下說明:

int    VarDesc;
char	  Array[MAXVAL];
那麼這兩個說明定義了外部變量VarDesc與Array,併爲之分配存儲單元,同時也用作供源文件其餘部分使用的說明。另一方面,如下兩行:
extern  int    VarDesc;
extern  char	  Array[];
  爲源文件剩餘部分聲明瞭VarDesc是一個int 類型的外部變量,Array是一個char數組類型的外部變量(數組大小在其他地方確定),但這兩個聲明並沒有建立變量或爲它們分配存儲單元,其中關鍵字extern表明該外部變量在其他地方被定義。
  根據C語言標準,外部變量雖然只能在某個文件中定義一次,但其作用域則是從其聲明處開始一直到其所在的被編譯的文件的末尾。因此其他文件可以通過extern說明來訪問它。

1.2 外部變量的使用方式

  如果外部變量被不同的函數所引用,並且這些函數沒有集中在一個源文件中,而是分佈在不同的源文件中,那麼函數在引用這些外部變量時,必須採取先聲明再使用的方式,否則,在編譯時會導致重複定義的編譯錯誤。
  若在多個文件的多個函數中引用外部變量,就需要在這些函數中重複聲明外部變量。這種方式可以解決編譯問題,但是代碼不夠簡潔。因此,在實際的編程中,大都採取了將外部變量統一定義在一個C源文件中,這個C源文件一般被稱爲global.c,然後在對應的頭文件中,一般爲global.h,聲明外部變量,最後在需要引用外部變量的源文件中使用#include "global.h"的方式,函數就可以引用所有的外部變量。因此,一般情況下,global.c內容爲:

#include "global.h"	

/* for example, define two vars */
int    VarDesc;
char	  Array[MAXVAL];
/* other external var define */
在對應的global.h頭文件的內容則爲:
#ifndef _GLOBAL_H   /* please insure _GLOBAL_H unique */
#define _GLOBAL_H   /* avoid quotation iterativly */

#ifdef __cplusplus
extern "C" {
#endif   /*__cplusplus */

/* for example, declare two vars */
extern  int    VarDesc;
extern  char	  Array[];

/* other external vars declaration */

#ifdef __cplusplus
}
#endif  /* __cplusplus */

#endif	/* _GLOBAL_H */
  此外,在實際的編程中,這兩個文件頭部還應當有公司copyright聲明、文件功能說明、版本說明、創建、修改歷史等。

2、函數的定義和使用

  根據C語言標準,函數只能被定義一次,而且在函數中,不能再定義函數,因此函數本身是外部的。

2.1 函數的定義與聲明

  定義函數是給出函數體的函數描述。一個函數只有在聲明之後才能被引用。函數聲明中,需給出函數名、返回類型、參數列表等。

  函數的作用域從其聲明處開始一直到其所在的被編譯的文件的末尾,如果一個函數在定義之前就要使用到,或者這個函數定義在與所要使用它的源文件不相同的源文件中,那麼就需要在使用該函數前,使用關鍵字extern聲明該函數,但由於函數默認是external的,因此函數聲明前的extern可以省略,這也是標準庫函數的頭文件中,函數聲明前沒有extern的原因,但在實際的編程中,一般不推薦這樣做,應當在函數聲明前加上extern。

2.2 函數的組織和使用

  如果某個函數需要引用另一個函數,則需要在引用該函數前聲明被引用的函數,否則可能會導致函數未定義錯誤。

  爲了避免被引用函數的重複聲明和方便函數的引用,在實際的編程之中,採用在對應的頭文件中,統一聲明函數的方式。需要引用某一個函數時,只需要在該函數的定義源文件中包含被引用函數的頭文件即可。
  在實際的編程中,在頭文件中聲明函數,即聲明函數原型,在對應的C源文件中,定義函數及其實現代碼。因此,函數說明的頭文件內容和格式爲:

#ifndef _FUNCNAME_H   /* please insure _ FUNCNAME _H unique */
#define _ FUNCNAME _H   /* avoid quotation iterativly */

#ifdef __cplusplus
extern "C" {
#endif   /*__cplusplus */

/* for example, declare functions */
extern  int    func (int, int, int);
/* of course, maybe declare functions like below 
* int    func (int, int, int);
*/
/* other functions declaration */

#ifdef __cplusplus
}
#endif  /* __cplusplus */

#endif	/* _ FUNCNAME _H */

而在對應的C源文件內容爲:
#include " funcname.h"

/* for example, define two vars */
int    func (int a, int b, int c)
{
		// functions body
}

/* other functions define */
在實際的函數頭文件和定義文件中還應當包含相應的頭文件等,以及公司copyright聲明、文件功能說明、版本說明、創建、修改歷史等。對於具體的函數,還應當有函數說明、輸入參數說明、返回說明、例外等。

3、靜態外部變量和函數

  如果某外部變量和函數僅供它們各自所在的源文件中的函數使用,而不能被其他函數訪問,那麼就必須使用static關鍵字定義外部變量和函數。static說明適用於外部變量與函數,用於把這些對象的作用域限定爲被編譯源文件的剩餘部分。通過外部static對象,可以把一些外部變量和函數隱藏在某個源文件中,使得這些外部變量和函數僅僅可以被該源文件使用和共享,但不能被該源文件之外的函數所引用。
  另外,static說明也可以用於說明內部變量。內部靜態變量就像自動變量一樣局部於某一個特定函數,只能在該函數中使用,但與自動變量不同的是,不管其所作函數是否被調用,它都是一直存在的,而不像自動變量那樣,隨着所在函數的調用與退出而存在與消失。換而言之,內部靜態變量是一種只能在某一特定函數中使用的但一直佔據存儲空間的變量。
  一般情況下,爲保證靜態外部變量和函數能夠被本源文件的函數所引用,需要在該源文件的所有函數之前定義靜態外部變量和函數。那麼,該C源文件的內容爲:

#include “funcname.h”	

/* for example, define one static external var and one static function */
static   int VarName = 0;
static   int function (int a)
{
		// function body
}
/* other static vars and functions */

/* for example, define one function */
char	  func (char*, char)
{		
		VarName = 5;
		function (VarName);
		// other function body
}

/* other functions define */
參考文獻:
  • B.W.Kernighan, D.M.Ritchie著,徐寶文譯,機械工業出版社 《C程序設計語言(第2版)》
  • Bjarne Stroustrup著,裘宗燕譯, 機械工業出版社 《C++程序設計語言(特別版)》
發佈了17 篇原創文章 · 獲贊 10 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章