本文我將採用Linux環境測試C語言存儲空間佈局,以及採用VC6.0來測試static的常見用法。採用linux環境來測試c語言存儲空間佈局,是因爲Linux很容易利用shell命令中的size命令查看到進程存儲區各段的大小。採用VC6.0來測試static的常見用法,是因爲我們利用VC6.0很容易創建一個工程,該工程可以包含很多源文件,這樣就很方便我們測試本文件與其他文件之間的關係了。
不管是在Linux下C程序還是Windows下C程序,他們都是由正文段、數據段、BSS段、堆、棧等段構成的,只不過可能他們的各段分配地址不一樣。Linux下的C程序正文段在低地址,而Windows下的C程序的正文段(代碼段)在高地址。所有不用擔心我用Linux環境和Windows環境共同測試帶來不正確的數據。
一、C語言存儲空間佈局
C語言一直由下面部分組成:
正文段(code segment/text segment,.text段):或稱代碼段,通常是用來存放程序執行代碼的一塊內存區域。這部分區域的大小在程序運行前就已經確定,並且內存區域通常屬於只讀,某些架構也允許代碼段爲可寫,即允許修改程序。在代碼段中,也有可能包含一些只讀的常數變量,例如字符串常量等。CPU執行的機器指令部分。
數據段(data segment,.data段):通常是用來存放程序中已初始化的全局變量的一塊內存區域。數據段屬於靜態內存分配。
BSS段(bss segment,.bss段):通常是指用來存放程序中未初始化的全局變量的一塊內存區域。BSS是英文Block Started by Symbol的簡稱。BSS段屬於靜態內存分配。
堆(heap):堆是用於存放進程運行中被動態分配的內存段,它的大小並不固定,可動態擴張或縮減。當進程調用malloc等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張);當利用free等函數釋放內存時,被釋放的內存從堆上被剔除(堆被縮減)。
棧(stack):棧又稱堆棧,是用戶存放程序臨時創建的局部變量,也就是我們函數大括號"{}"中定義的變量(不包括static聲明的變量)。除此以外,在函數被調用時,其參數也會被壓入發起調用的進程棧中,並且等調用結束後,函數的返回值也會被存放在回棧中。由於棧的先進先出特性,所有棧特別方便用來保存/恢復調用現場。從這個意義上講,把堆棧看成一個寄存、交換臨時數據的內存區。
【測試】:採用Linux環境測試
1、測試代碼如下,文件名爲progressStruct.c
保存後,輸入gcc progressSturnct.c -o progressStruct編譯生成二進制文件(可執行文件),然後輸入size progressStruct查看進程progressStruct內存各段大小
text->正文段 data->數據段,存儲已初始化全局變量段 bss->存儲未初始化全局變量段 dec->以十進制顯示總大小 hex->以十六進制顯示總大小
2、修改progressStruct.c文件,修改後代碼如下:
保存後,輸入gcc progressSturnct.c -o progressStruct編譯生成二進制文件(可執行文件),然後輸入size progressStruct 查看進程progressStruct內存各段大小
3、繼續修改progressStruct.c文件,修改後代碼如下:
保存後,輸入gcc progressSturnct.c -o progressStruct編譯生成二進制文件(可執行文件),然後輸入size progressStruct 查看進程progressStruct內存各段大小
4、3、繼續修改progressStruct.c文件,修改後代碼如下:
保存後,輸入gcc progressSturnct.c -o progressStruct編譯生成二進制文件(可執行文件),然後輸入size progressStruct 查看進程progressStruct內存各段大小
其他非主函數中的變量存儲在堆棧區
二、面向過程程序設計中的static
1、全局靜態變量
在全局變量之前加上關鍵字static修飾,全局變量就被定義成一個全局靜態變量
- 內存中的位置:靜態存儲器(靜態存儲區在整個程序運行期間都存在的)
- 初始化:未初始化的全局靜態變量會被程序自動化爲0
- 作用域:全局靜態變量在聲明它的文件之外是不可見,即其他文件不能使用被static修飾的變量。只能在從定義處到文件結尾中被使用。
2、局部靜態變量
- 內存中的位置:靜態存儲器
- 初始化:未經初始化的局部變量會被程序自動初始化爲0
- 作用域:作用域仍爲局部作用域,當定義它的函數或語句塊結束的時候,作用域隨之結束。