不管我們以後是自己寫**還是讀別人的**,都應該想想這個變數預設儲存的位置。在我們以後的嵌入式開發中,技巧性的**越來越多的時候,我們可能把某一些**放在一段。我們可以通過修改變數或者**預設放置的段,讓它被放到其它的段中。我們也可以自己定義乙個新的段。
隨著執行,棧空間是隨時會變化的。棧空間臨時的去儲存一些變數,當我們進入乙個函式,系統就會在棧空間去分配一片記憶體去儲存這個函式裡面所有的變數。當函式執行完之後,這一片記憶體的資料就被銷毀了。當我們在初學的時候,就千萬不要犯把區域性變數給別人的錯誤。
全域性的資料空間和唯讀資料段,**段都是在執行之前就已經分配好了的。所以我們在列印資訊的時候應該盡量不要使用太多的字串,否則容易導致程式的可執行檔案很大。所以我們在最後發布程式的release版本裡面去除了我們一些除錯用的資訊。
測試**如下
我們在main函式外面申請了乙個全域性變數
b,但是我們並沒有為這個
b賦初始值。它僅僅只是為這個變數圈出了一塊記憶體,裡面有為全域性變數自動初始化的0值。
執行結果如下
上面的結果是沒有變數b的結果,下面是新增全域性變數
b的結果。
bss段就是未初始化的全域性變數儲存的段,上面的全域性變數
b就在這個段中分配了四個位元組(儘管系統已經將它初始化為
0,但是並不是我們初始化的)。
測試**如下
我們只是將未初始化的變數b將它初始化了。
執行結果如下
可以看到,在未初始化的字段裡面少了四個位元組,而在已初始化的字段裡面多了四個位元組。所以我們也將date稱做全域性初始化資料空間,
bss稱做全域性未初始化資料空間。區域性的變數不管有沒有初始化都是儲存在棧上。
static關鍵字宣告變數的時候,系統就會將它認為是乙個全域性變數,即使它在函式內部宣告。此時,它分配的位址也就在全域性的資料空間。
測試**如下
執行結果如下
這就是宣告變數a為靜態資料前後的結果,此時分配的段為全域性未初始化資料空間,現在它不在棧中,那麼就不會隨著棧的彈出而被銷毀了。靜態資料段的消失是在整個程式都消失之後才會消失。
測試**如下
我們在兩個函式裡面宣告了兩個一樣的變數a,雖然它們是一樣的名字,但是它們在系統中的訪問卻是不一樣的,
fun函式裡面的
a++呼叫的是該函式裡面的。
main
函式也是對應的。
執行結果如下
這是新增乙個fun函式前後的結果,編譯器並沒有對兩個全域性變數報錯,它將
fun函式裡面的靜態變數
a放到了
data
段中。雖然它們是一樣的變數名,但是在編譯器中,它們有不一樣的字尾。
我們可以通過nm build檢視靜態的資料段,前面為位址,兩個變數的字尾是不一樣的。
static相當於全域性的資料空間的乙個顯示分配的符號,它可以更改區域性資料的預設儲存段,雖然它們的訪問依然是區域性的,但是儲存位置已經在全域性資料段中了。
C語言記憶體分布之資料段
不管我們以後是自己寫 還是讀別人的 都應該想想這個變數預設儲存的位置。在我們以後的嵌入式開發中,技巧性的 越來越多的時候,我們可能把某一些 放在一段。我們可以通過修改變數或者 預設放置的段,讓它被放到其它的段中。我們也可以自己定義乙個新的段。隨著執行,棧空間是隨時會變化的。棧空間臨時的去儲存一些變數...
C語言記憶體分布
動態記憶體分配,c語言動態記憶體分配詳解 c語言知識總結 十一 記憶體管理 c語言記憶體分布圖 段 const常量,字串常量 資料段 已初始化全域性變數 已初始化全域性靜態變數 區域性靜態變數 常量資料 bss段 未初始化全域性變數 未初始化全域性靜態變數 棧 區域性變數 函式引數 堆 動態記憶體分...
C語言 記憶體分布詳解
一 乙個c c 程式占用的記憶體分為以下幾個部分 堆區 heap 全域性 靜態區 static 示例 int a 10 全域性變數 全域性 靜態 初始化區 int i 全域性變數 全域性 靜態 未初始化區 main char s1 abcdef s1 在靜態區,abcdef 無需額外存放,存在陣列s...