C語言詳解(2)變數的實質
變數
關於C語言詳解系列部落格的目錄:https://blog.csdn.net/snake_lp/article/details/78630717點選開啟連結
一,概述
變數實際上是一段連續的儲存空間的別名。一個變數名就是代表記憶體某一段地址的資料。程式中通過變數來申請儲存空間,並將這段儲存空間命名為變數名。程式設計師通過變數的地址就可以使用這段儲存空間的內容了。
資料型別是模板,變數是實體。變數所佔用的儲存空間就是以定義變數的資料型別的記憶體大小為步驟的。
變數的實質就是一塊可以被使用者修改的記憶體資料,主要強調的是資料可以修改,所以稱之為變數。
變數的兩個常用語:
1,作用域:指的是變數作用的範圍。在哪個範圍變數是可用的,有效的;
2,生命週期:指的是變數存在的時間長度。從建立到銷燬的時間段,即該變數佔用該段記憶體的時間長度。
二,變數的分類
從作用域分的話,可以分為全域性變數,區域性變數。
全域性變數
全域性變數就是在函式之外申明的變數。一般情況下,全域性變數在宣告檔案的任何地方都是有效的。但是也存在例外,那就是全域性變數和區域性變數重名的時候,區域性變數的優先順序高,在區域性變數的作用區域內全域性變數就不可見了。
如下列程式碼:
#include <stdio.h>
int val1 = 0; / *全域性變數* /
int val2 = 0;
void func(void)
{
int val1 = 8; / *區域性變數,僅在func函式中有效* /
printf(“[func] val1 =%d \ n”,val1);
}
int main(void)
{
int val1 = 5; / *區域性變數* /
val2 = 9;
printf(“[main] val1 =%d,val2 =%d \ n”,val1,val2);
FUNC();
返回0;
}
執行結果為:
從上述程式碼的執行結果可以看出全域性變數的作用範圍。
這種變數的定義方式,在Ç語言的語法上沒有任何的問題,但是在實際專案工程中需要避免這種現象。區域性變數和全域性變數不要使用同一個變數名字,這樣的做法會降低程式的可讀性。
對於全域性變數的作用範圍,應該和編譯器有關係的一個全域性變數有的編譯器認為這個變數是在工程的全部檔案中可見;有的編譯器認為是隻在本檔案中可見由於Ç語言設計的中心思想是:未宣告,不可用所以為了提高程式碼的移植性,請使用以下的做法:
1.如果需要跨檔案使用變數,請使用extern來顯示修飾;在一個檔案中定義變數int val;在需要使用的檔案中使用extern宣告變數extern int val;
2.如果僅在當前檔案中使用,請使用靜態現象修飾static int val ;.
2.區域性變數
在程式碼示例中,main函式和func函式中val1就是區域性變數。更直接的說,在程式碼塊(以{}包括的程式碼)中定義的變數就是區域性變數。它的作用域僅僅在程式碼塊中,如果在其他地方使用,在編譯的時候,就會報錯[變數未定義]。區域性變數在函式呼叫時由系統自動分配儲存區(堆疊),在不同的函式中,堆疊的區域是不一樣的,所以在不同的函式中定義的區域性變數可以使用相同的名字。比如說函式的形參,函式內部定義的變數都是區域性變數,在函式呼叫結束之後,區域性變數就會銷燬。
從生命週期來劃分的話,可以分為靜態變數、動態變數、堆變數。
1. 靜態變數(static variable)
全域性變數和使用static修飾的區域性變數都具有靜態的儲存期。它們從程式的開始到程式的結束一直都存在的,所以存稱之為靜態變數。靜態變數在編譯的時候就分配了記憶體空間並且進行了賦值的操作,所以在程式執行時它就已經存在了初始化值。以後每次呼叫函式時,不在需要重新賦值了而是保留上一次函式呼叫結束時候的數值。
如果在定義靜態變數時不對它進行賦值操作,在編譯的時候編譯器會自動賦值為0(對數值型變數)或者空字元(對字元型變數)。
需要注意的是,靜態區域性變數在函式呼叫時仍然存在,但是對其他函式不可見,即其他函式是不能使用它的。
2. 動態變數(auto variable)
沒有被指定static型別的區域性變數和暫存器變數(register variiable)都是自動變數。函式的形參以及程式碼中定義的變數都屬於自動變數。這是C語言中應用最廣泛的一種變數,這類變數是棧分配的,是動態分配儲存空間的。
以函式的形參為例:當呼叫該函式時,為形參分配儲存空間,當函式呼叫結束時,就自動釋放這些儲存空間。對程式碼中定義的變數(包含函式中定義的變數),當執行到變數申明語句時,系統會為這些自動變數分配空間,當程式流程離開程式碼塊(函式),這些變數就會自動銷燬,其佔用的記憶體空間就會被釋放。
自動變數(即動態區域性變數)屬於動態儲存的類別,儲存在動態儲存空間(而不是在靜態儲存區空間),函式呼叫時分配空間,呼叫結束就釋放。
自動變數如果不賦初值的話,則它的值就是一個不確定的隨機值。這是由於每次呼叫函式結束時儲存單元就釋放,下次呼叫時又重新分配儲存空間,而所分配的儲存空間也是不確定的,故變數的值就無法確定。
3.堆變數
通過的malloc()函式分配記憶體空間的變數被存放在堆中,故稱之為堆變數。並且這類的“堆”和資料結構中的堆沒有任何的連續。是硬體平臺儲存的位置和方式。
堆變數需要手動分配記憶體,也需要手動釋放記憶體,也就是說它從建立時起就一直存在直到使用免費()函式釋放位置當然,建議在程式設計中需要做到:誰建立,誰釋放。
在嵌入式開發中一般儘量少是使用堆變數,如果沒有控制好,很容易造成記憶體佔用過大或者未釋放溢位的問題,另外現在的MCU的記憶體資源基本上可以滿足我們的開銷。