變數的定義與宣告

2021-05-23 11:37:37 字數 4093 閱讀 2332

1.變數的定義

從前面的章節可以看出,程式中所有的東西幾乎都有名字。然而字面量卻是個例外,它沒有名字。那麼使用變數,我們就可以為某個值取名字了。實際上,我們是為系統記憶體中用於儲存資料的某塊空間取名字。

ansi c規定:變數必須「先定義、後使用」,因此當用c定義變數時,不僅需要指定變數名,而且還必須告訴編譯器其儲存的資料型別,變數型別告訴編譯器應該在記憶體中為變數名分配多大的儲存單元,用來存放相應變數的值(變數值),而變數僅僅是儲存單元的別名,供變數使用的最小儲存單元是位元組(byte)。

由此可見,每個變數都佔據乙個特定的位置,每個儲存單元的位置都由「位址」唯一確定並引用,就像一條街道上的房子由它們的門牌號碼標識一樣。即從變數中取值就是通過變數名找到相應的儲存位址,然後讀取該儲存單元中的值,而寫乙個變數就是將變數的值存放到與之相應的儲存位址中去。

由於變數的定義不是可執行**,因此要求區域性變數的定義必須位於用「{}包圍的程式塊」的開頭,即在可執行**的前面。比如:

int lowerlimit = 80; // 定義lowerlimit為整型變數

即在定義lowerlimit為int型別資料時,系統就已經為變數lowerlimit分配了儲存單元。請注意區分變數名和變數值這兩個不同的概念,其中,lowerlimit為變數名,80為變數lowerlimit的值,即存放在變數lowerlimit的儲存單元中的資料。

那麼到底如何獲得變數的位址呢?c語言使用「&(位址運算子)加變數名」的方式獲取變數的位址,比如,&lowerlimit就代表變數lowerlimit的位址,詳見後續相關章節的描述。

乙個定義只能指定一種變數型別,雖然後面所帶的變數表可以包含乙個或多個該型別的變數:

int lowerlimit , upperlimit , sum;

但如果將乙個定義語句中的多個變數拆開在多個定義語句中定義的話:

int lowerlimit; // lowerlimit為資料下限

int uppelimit; // upperlimit為資料上限

int sum; // sum為求和的結果

則可在各個定義語句中新增注釋,則大大提高了程式的可閱讀性,而且修改起來更加方便,但c編譯器會忽略在每行右邊用於描述變數用途的注釋語句。與此同時還可以在定義中,對變數進行初始化,即允許在變數名的後面緊跟乙個等號以及乙個表示式。

int lowerlimit = 1;

int upperlimit = lowerlimit+50;

int sum;

2.外部變數的宣告

由於變數lowerlimit是在別的檔案中定義的,那麼只要在引用之前用關鍵字extern對該變數作「外部變數宣告」即可,無需再為變數lowerlimit分配儲存單元,這種情況稱之為宣告或引用性宣告。比如:

extern int lowerlimit; // 將已定義的外部變數lowerlimit的作用域擴充套件到此

在這裡將extern置於變數前,就是為了告訴編譯器變數lowerlimit這個名字已經在別的檔案中被定義了,因此遇到此變數時,需在其它模組中尋找與之相應的定義。

有時程式是由多個源程式檔案組成的,那麼只需要在其中任乙個檔案中定義外部變數lowerlimit,而在另乙個檔案中用extern對變數lowerlimit作「外部變數宣告」,即可將外部變數的作用域擴充套件到其它檔案。

當extern用於宣告外部變數時,則型別名可寫也可不寫,由於宣告變數不是定義變數,則可以不指定型別,只需寫出變數名即可。比如:

extern lowerlimit;

☛ 注意:extern不僅可用於宣告變數,而且還可以用於宣告陣列和指標,以及用於宣告外部函式,詳見後續相關章節的描述。

3.靜態變數的定義

當用static修飾變數時,則全域性變數與區域性變數都儲存在記憶體的靜態區。即便函式執行結束,而靜態變數的值都不會被銷毀,以後仍然還可以繼續使用。

(1)靜態全域性(外部)變數

當static用於定義外部變數時,則變數僅被所定義的檔案使用,而其它檔案則無法使用它。比如:

static unsigned char __guctask0; // 任務0測試變數

使用靜態全域性變數的好處就是在進行模組化程式開發時,不用擔心外部變數名的衝突,只需在每個檔案中定義全域性變數時加上static即可。

(2)靜態區域性變數

靜態區域性變數則是在函式體內定義的,那麼只能在這個函式中使用。

☛ 注意:static還可以用於修飾函式,如果在函式前加static,則該函式只能成為被本檔案中的其它函式所呼叫的靜態函式(內部函式),其好處就是不用擔心函式名的衝突,便於模組化開發,詳見後續相關章節的描述。

4.常變數的宣告

為了提高程式的可閱讀性與可維護性,ansi c允許使用者命名常量(named constant,宣告為const的變數)。

當它被初始化之後,它的值便不能改變,因此const主要用於宣告其值不會修改的變數。

ansi c規定:可以使用const關鍵字宣告常量,修飾符const可以用在型別說明符前,也可以用在型別說明符後。比如:

int const max_length = 78; // 命名常變數的最佳方式是使用大寫字母

const int max_length = 78; // max_length的初值為78

雖然const修飾max_length的值是常量,而實際上max_length卻是乙個「唯讀變數」。編譯器僅給出了與只

讀變數max_length對應的記憶體位址,卻並沒有為唯讀變數max_length分配儲存單元,而是將它們儲存在符號表中,在編譯時直接進行「替換」優化。因此使用const修飾常變數,可以節省空間,避免了不必要的記憶體分配,而且執行效率更高。

既然使用const也可以定義常量,那麼它與符號常量到底有什麼區別呢?

由於const定義的常量有資料型別,因此編譯器會對用const宣告的唯讀變數進行型別校驗,以減少出錯的機率;雖然可以使用#define指令定義符號常量,但它在預編譯進行字元替換之後,符號常量就不存在了,因為#define巨集定義的立即數是沒有型別的。很多開發環境只能除錯const宣告的常量,而不支援#define。由此可見,const比#define宣告常量更有優勢。因此const的引入不僅消除預編譯指令的缺點,而且繼承了預編譯指令的優點。

雖然在很多時候const是#define的優化,但有時#define比const有優勢,因為#define不僅宣告常量,而且還可以宣告「帶巨集的引數」,這是const無法做到的,所以說const相對於#define的優勢僅限定在宣告常量上。

☛ 注意:const除了可以修飾唯讀變數之外,還可以用於修飾陣列、指標、函式的引數與函式的返回值,詳見後續相關章節的描述。

5. 識別符號

ansi c規定識別符號只能由字母、數字和下劃線3種字元組成,且第1個字元必須為字母或下劃線。比如:

__guctask0

☛ 注意:c是區分大小寫字母的語言,也就是說,由相同字母組成的字元,如果大小寫不同,就會被看做不同的字元。比如,命名age與sum的變數與age或age以及sum的變數就是不同的變數。一般來說,變數名常用小寫字母來表示,比較符合人們的閱讀習慣。

雖然ansi c並沒有規定識別符號的長度,但各個編譯器都有自己的規定,比如,turbo c則允許變數名最多不超過32個字母。

☛ 關鍵知識點:變數的宣告與定義

l 宣告與定義的區別

廣義地說,宣告包含定義,但並非所有的宣告都是定義。對於「int lower_limit;」來說,它既是宣告又是定義;而對「extern lower_limit;」來說,它是宣告不是定義。

「宣告」僅僅告訴編譯器變數名的值的型別而已,不會生成目標**,當然也不會給它分配儲存空間,更不會增大可執行程式的體積。由於宣告並不分配儲存空間,因此同乙個宣告可以在程式中多次出現。它的位置可在執行**之外,也可在執行**裡面。

而「定義」不僅要告訴編譯器變數名的值的型別,而且還要給變數分配儲存空間。既然在定義變數時就已經建立了儲存空間,那麼變數的定義只能出現一次,且它的位置在所有執行**之外。

由於系統是根據外部變數的「定義」來分配儲存空間的,因此對外部變數的初始化只能在「定義」時進行,不能在「宣告」中進行,而「宣告」則是告訴編譯器,該變數已經存在。

l 變數與函式的多源檔案共享

當希望在多個原始檔中共享變數或函式時,需要確保定義與宣告的一致性。最好的安排是在某個相關的「.c」檔案中定義,然後在「.h」檔案(標頭檔案)中進行外部宣告,在需要使用的時候,只要包含對應的標頭檔案即可。定義變數的「.c」檔案也應該包含該標頭檔案,以便編譯檢查定義和宣告的一致性。

變數的定義與宣告

我們在程式設計中,時時刻刻都用到變數的定義和變數的宣告,可有些時候我們對這個概念不是很清楚,知道它是怎麼用,但卻不知是怎麼一會事,下面我就簡單的把他們的區別介紹如下 望我的指點對你受益 變數的宣告有兩種情況 1 一種是需要建立儲存空間的。例如 int a 在宣告的時候就已經建立了儲存空間。2 另一種...

變數的宣告與定義

請看下邊小程式 1 int i 定義性宣告 defining declaration 或定義 definition 2extern int j 引用性宣告 referencing declaration 3int k nullptr 定義性宣告 defining declaration 很明顯,上述...

變數宣告與變數定義的區別

int a 定義變數但不初始化 建立乙個變數,為這個變數分配一塊int資料型別所佔記憶體空間大小的記憶體空間並命名 int a 1 定義變數並初始化 建立乙個int型別的 變數名為a的 初始值為1的 變數 int 編譯器為變數分配記憶體空間的大小 a 這塊記憶體空間的名稱 1 在這塊記憶體空間中儲存...