標籤:class 初始化 org init 一個 變數 函數 不能 結果
C語言記憶體分布
典型的C語言程式記憶體表示分區共有5個部分:
- 本文段 Text segment
- 已初始化資料區段(資料區段)Initialized data segment
- 未初始化資料區段(bss)Uninitialized data segment
- 堆 Stack
- 棧 Heap
具體分布圖
各個分區的作用
- 本文段
- 已初始化資料區段(資料區段)
- 包含程式中需明確賦初始值的變數
- 儲存已經初始化的全域變數
- 未初始化資料區段(BSS)
- 在程式開始執行之前,核心將此段中的資料初始化為0或null 指標
- 儲存未初始化的全域變數(注意:即使是賦值為0也是未初始化!)
- 棧
- 儲存自動變數及每次函數調用所需儲存的資訊
- 每次函數調用時,存放其返回地址及調用者的環境資訊(如某些機器寄存器的值)
- 為最近被調用的函數分配自動變數和臨時變數的儲存空間
- 堆
初始化?
上面提到,對全域變數來說,如果是賦值為0仍是未初始化。下面給出實際實驗結果:
範例程式碼1
#include <stdio.h>int a;int main(int argc, char const *argv[]){ printf("hello\n"); return 0;}
編譯後查看記憶體分布:
範例程式碼2
#include <stdio.h>int a = 0;int main(int argc, char const *argv[]){ printf("hello\n"); return 0;}
編譯後查看記憶體分布:
可以看到,各個儲存地區數值沒有變化。
範例程式碼3
#include <stdio.h>int a = 1;int main(int argc, char const *argv[]){ printf("hello\n"); return 0;}
編譯後查看記憶體分布:
可以看到,對全域變數進行真正的初始化之後,bss少了4個位元組,data段多出了4個位元組。
關於static的問題範例程式碼4
先看看相對上一例子,多了一個局部變數之後的記憶體分布。
#include <stdio.h>int a = 1;int main(int argc, char const *argv[]){ int b; printf("hello\n"); return 0;}
編譯後查看記憶體分布:
可以看到,記憶體分布是沒有變化的,局部變數b會在棧上分配到記憶體。
範例程式碼5
如果把b定義成static呢?
#include <stdio.h>int a = 1;int main(int argc, char const *argv[]){ static int b; printf("hello\n"); return 0;}
編譯後查看記憶體分布:
可以看到,此時bss上多出了8個位元組。
範例程式碼6
如果給b賦初始值0呢?
#include <stdio.h>int a = 1;int main(int argc, char const *argv[]){ static int b = 0; printf("hello\n"); return 0;}
編譯後查看記憶體分布:
可以看到,跟上一個例子相比沒有變化,說明跟全域變數一樣,static變數賦值為0仍是未初始化。
範例程式碼7
如果給b賦初始值1呢?
#include <stdio.h>int a = 1;int main(int argc, char const *argv[]){ static int b = 1; printf("hello\n"); return 0;}
編譯後查看記憶體分布:
可以看到,bss少了4個位元組,而data多了4個位元組,說明靜態變數和全域變數同理,初始化之後是存在data段中的。
關於static的用處範例程式碼8
#include <stdio.h>int x = 4;void incre() { static int x = 1; x *= x + 1; printf("%d\n", x);}int main(int argc, char const *argv[]){ int i; for (i = 1; i < x; i++) { incre(); } return 0;}
運行結果為:
可以看到,函數incre中x的範圍存在於其局部,但是卻在每次調用函數的時候沿用之前的值!這是因為static定義的變數是靜態變數,有著靜態儲存位置(變數儲存位置固定不動,若在代碼中已經初始化則存在於data段,否則存在於bss段),而不是存在於棧上,因此每次調用函數讀取到的變數的值都是靜態儲存區的值。
static的意義:
- 全域靜態變數
- 不會被其它檔案所訪問和修改
- 其它檔案中可以使用相同名字的變數,不會發生衝突
- 局部靜態變數
- 靜態函數
- 其它檔案中可以定義相同名字的函數,不會發生衝突
- 靜態函數不能被其它檔案所用
- 靜態函數會被分配在一個一直使用的儲存空間,直到程式退出,避免了調用函數時進棧出棧,提升運行速度
參考書目
- Unix環境進階編程(中文第三版)
- C primer plus(中文第五版)
參考部落格
C語言儲存空間布局以及static詳解——奔人之旅
C語言記憶體分布