C語言全域變數和局部變數總結

來源:互聯網
上載者:User


—————————————————————————————————————————————————————————————————————————————


只有不斷的學習,不斷的進步,才能不被替代。


只有你的不可替代性才決定你的價值。


-----2016年11月18日


—————————————————————————————————————————————————————————————————————————————


第一部分問題:

今天一個小夥伴問我一個問題,如圖程式1:



咋一看沒有問題啊,後來想想確實有問題,這個c=a+a;似乎是語句,必須在函數體內才能執行,後來就看到這麼一句話:

指派陳述式需要有函數執行,c語言最基本的執行體是函數,你可以初始化,但不能在函數體外賦值。

在VC++中,確實出錯,指標的地方出錯,錯誤提示:


錯誤說的是:初始化必須是一個常量。

然後我就去掉運算的c。如圖程式2:


顯示可以正常啟動並執行。然後就比較鬱悶,就問了QQ好友(矩陣)。正確答案如下:

函數體外只能進行初始化,不能進行賦值運算。如圖程式3:


提示的錯誤是:變數a被重複賦初值。

其實正確的理解就是:函數體外只能進行初始化,不能進行賦值運算。為什麼第二個程式可以執行。

因為,C語言執行過程中,對代碼進行了最佳化,把程式2中的 int a; a=10;  最佳化為一句話:int a=10;這就是初始化。所以程式2是正確的,程式3中,初始化過程中:int a=10;int a=17;肯定就出錯了。重複初始化。程式1中,語句必須在函數體內執行,函數體外只能進行初始化。


第二部分全域變數與局部變數

定義:

局部變數(Local Variable):定義在函數體內部的變數,範圍僅限於函數體內部。離開函數體就會無效。再調用就是出錯。

全域變數(Global Variable):定義:所有的函數外部定義的變數,它的範圍是整個程式,也就是所有的源檔案,包括.c和.h檔案。

全域變數的例子,如圖程式4:

提示的錯誤是 變數 x 沒有定義,原因是:

C語言代碼是從前往後依次執行的,由於 x 定義在函數 func1() 之後,所以在 func1() 內無效;修改程式如下,程式5:



可以看出,輸出正確的答案,所以全域變數必須定義在我們需要用它的函數體之前。

然後,在看下局部變數:


注意事項:

①在main函數中定義的變數也是局部變數,只能在main函數中使用;同時,main函數中也不能使用其他函數中定義的變數。main函數也是一個函數,與其它函數地位平等。

②形參變數、在函數體內定義的變數都是局部變數,實參給形參傳值的過程也就是給局部變數賦值的過程。

③可以在不同的函數中使用相同的變數名,它們表示不同的資料,分配不同的記憶體,互補幹擾,也不會發生混亂。

④在語句塊(由一對{}包含的若干條語句)中也可以定義變數,它的範圍只限於當前的語句塊。


一道綜合練習題:



①先調用fun1(),在fun1()中,有局部變數n,所以輸出的結果是  n:20;

②對於fun2(),使用了形參,形參的作用範圍也是整個函數內(實參給形參傳值的過程也就是給局部變數賦值的過程),所以輸出的結果是  n:30;

③對於fun3(),沒有局部變數,所以全域變數定義的 n 對所有的函數都可見。所以輸出的結果是  n:10;

④根據局部變數注意事項第四條。所以輸出的結果是  n:40;

⑤3C語言規定,只能從小的範圍向大的範圍中去尋找變數,而不能反過來,使用更小的範圍中的變數。對於 main() 函數,即使代碼塊中的 n 離輸出語句更近,但它仍然會使用 main() 函數開頭定義的 n,所以輸出結果是 30。


所以結果是:



第三部分記憶體的分區和變數的儲存


記憶體中供使用者使用的儲存空間分為三部分:程式區  、靜態儲存區、動態儲存裝置區。

變數的分類:

①從空間上分配:從變數的範圍可以分成:局部變數和全域變數。

②從變數的存在時間(生存周期)可以分成:靜態儲存和動態儲存裝置。

靜態儲存:程式在運行期間分配固定的儲存方式。

動態儲存裝置:程式在運行期間根據需要動態分配儲存空間。

全域變數全部儲存在靜態儲存區。在程式開始執行過程中給全域變數分配空間,程式執行完畢就釋放空間。程式執行過程中固定的分配空間,而不需要動態進行分配是釋放。

動態儲存裝置區主要存放以下資料:函數的形參、自動變數(沒有加static的局部變數)、函數調用的現場現場保護和傳回值。

動態儲存裝置區的資料,在函數開始調用時分配動態儲存裝置空間,函數結束時釋放這些空間。

C語言中每個變數有兩個屬性:第一資料類型;第二儲存屬性。

auto 變數:

函數中的局部變數,如果不專門的聲明為 static儲存,都是動態分配儲存空間。資料存放區在動態儲存裝置區內。函數中的形參和函數中的變數都屬於此類,調用該函數時候系統自動的分配空間,在函數結束的時候,釋放該空間。這些局部變數被稱為自動變數。自動變數用 auto關鍵字聲明(可以省略auto )。

static 變數:

有時候希望我們調用的函數在釋放的時候不消失能保留原值,這就需要定義為靜態局部變數。用關鍵字 static聲明。
看一段程式:


對靜態局部變數的說明:
1)靜態局部變數屬於靜態儲存類別,在靜態儲存區內分配儲存單元。在程式整個運行期間都不釋放。而自動變數(即動態局部變數)屬於動態儲存裝置類別,占動態儲存裝置空間,函數調用結束後即釋放。
2)靜態局部變數在編譯時間賦初值,即只賦初值一次;而對自動變數賦初值是在函數調用時進行,每調用一次函數重新給一次初值,相當於執行一次指派陳述式。
3)如果在定義局部變數時不賦初值的話,則對靜態局部變數來說,編譯時間自動賦初值0(對數值型變數)或Null 字元(對字元變數)。而對自動變數來說,如果不賦初值則它的值是一個不確定的值。

register變數
為了提高效率,C語言允許將局部變數得值放在CPU中的寄存器中,這種變數叫“寄存器變數”,用關鍵字register作聲明。

說明:
1) 只有局部自動變數和形式參數可以作為寄存器變數;
2)一個電腦系統中的寄存器數目有限,不能定義任意多個寄存器變數;
3)局部靜態變數不能定義為寄存器變數。


用extern聲明外部變數
外部變數(即全域變數)是在函數的外部定義的,它的範圍為從變數定義處開始,到本程式檔案的末尾。如果外部變數不在檔案的開頭定義,其有效作用範圍只限於定義處到檔案終了。如果在定義點之前的函數想引用該外部變數,則應該在引用之前用關鍵字extern對該變數作“外部變數聲明”。表示該變數是一個已經定義的外部變數。有了此聲明,就可以從“聲明”處起,合法地使用該外部變數。

extern 例子:


在 main 函數體外定義的變數,A 、B(外部變數:它的範圍為從變數定義處開始,到本程式檔案的末尾。)。想要在main中引用必須加關鍵字:extern 。


第三部分:C語言的堆與棧

和棧的第一個區別就是申請方式不同:棧(英文名稱是stack)是系統自動分配空間的,例如我們定義一個 char a;系統會自動在棧上為其開闢空間。而堆(英文名稱是heap)則是程式員根據需要自己申請的空間,例如malloc(10);開闢十個位元組的空間。由於棧上的空間是自動分配自動回收的,所以棧上的資料的生存周期只是在函數的運行過程中,運行後就釋放掉,不可以再訪問。而堆上的資料只要程式員不釋放空間,就一直可以訪問到,不過缺點是一旦忘記釋放會造成記憶體泄露。






聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.