C語言 函式內區域性陣列

2021-09-06 03:48:14 字數 1357 閱讀 2946

直接看這個例子

void test()

對於上面的test函式, 如果連續呼叫兩次, 會得到什麼樣的輸出

答案是:

abcabc

abc這是我實際測出的值, 我當時很迷惑, 為什麼b是區域性陣列, 當函式結束時這部分記憶體就被釋放了, 而第二次呼叫test時, b陣列的值仍然是abc.

可能有人說區域性陣列是存放在靜態儲存區的..., 對嗎?

好, 下面就來解答這個問題,

編譯時程式分為3段:text段,data段,bss段

text段:就是放程式**的,編譯時確定,唯讀,

data段:存放在編譯階段(而非執行時)就能確定的資料,可讀可寫,就是通常所說的靜態儲存區,賦了初值的全域性變數和靜態變數存放在這個區域,常量也存放在這個區域

bss段:定義而沒有賦初值的全域性變數和靜態變數,放在這個區域

執行時程式還需要的區域

堆疊 (stack): stack就是存放區域性變數, 臨時變數的, 如呼叫函式時, 存放函式的區域性變數

堆 (heap):heap就是用來存放動態分配的記憶體的, 即是通過malloc或是new分配的

明確一點, 區域性變數一定是存放在堆疊的, 不可能放在靜態區, 除非你加上static, 那麼為什麼會出現上面的現象?

透過現象看本質...

首先要理解堆疊的實現, 對於我們說的堆疊壓入, 丟擲操作, 並不是象我們想的那樣實現的, 丟擲後內容就不存在了

堆疊的操作就是通過移動棧頂指標實現的, 棧頂指標和棧底指標之間就是當前堆疊的大小

所以第一次呼叫test時, 分配了25位元組的堆疊空間, 此時棧頂指標加25, 你對前4個位元組賦值, 當函式結束時, 進行丟擲操作, 即棧頂指標減25

但要注意, 此時系統並不會自動清空這25位元組, 即他們仍然保留原來的內容.

第二次呼叫test時, 仍然分配了25位元組的堆疊空間, 此時棧頂指標再加25, 其實這只是巧合, 分配了和第一次呼叫相同的空間, 並且內容都一樣.

這就解釋了我們上面說的那個問題.

想要驗證很容易, 只需要在兩次test呼叫中, 呼叫一次其他函式, 如果該函式修改了那段堆疊, 那麼在第二次test中,就不會看到abc的初始值了. 這裡絕對不要誤認為區域性陣列是放在靜態儲存區的......千萬不能被現象所迷惑...

總結

1. 通過malloc, 或區域性陣列分配的堆空間或堆疊空間, 首先用memset清0, 這是很多新手會忽視的, 這個很重要, 剛分配的空間的內容是不可預知的, 不清空很容易會影響程式的邏輯.

2. 在函式中不應該直接建立大的陣列, 因為區域性變數是分配在堆疊上的, 這樣做, 不但效率不高, 而且會導致堆疊溢位, 堆疊空間是有限的.

對於大的陣列, 應該通過malloc分配堆空間來解決.

C語言 函式內區域性陣列

直接看這個例子 void test 對於上面的test函式,如果連續呼叫兩次,會得到什麼樣的輸出 答案是 abcabc abc這是我實際測出的值,我當時很迷惑,為什麼b是區域性陣列,當函式結束時這部分記憶體就被釋放了,而第二次呼叫test時,b陣列的值仍然是abc.可能有人說區域性陣列是存放在靜態儲...

C語言中如何傳遞函式內的區域性變數

有一種寫法,可以用乙個返回指標來返回區域性變數 int example end example這種寫法在編譯時可以通過,但在實際執行中,程式會在這裡崩潰。究其原因,主要是因為c語言中,區域性變數將被儲存在棧中。在函式呼叫結束後,棧中元素的生命週期也到了盡頭。而此時傳遞出去的指標就成了乙個野指標。而這...

C 中函式內區域性變數的位元組對齊

所位資料對齊,是指資料所在的記憶體位址必須是該資料長度的整數倍,dword資料的記憶體起始位址能被4除盡,word資料的記憶體起始位址能被2除盡,x86 cpu能直接訪問對齊的資料,當他試圖訪問乙個未對齊的資料時,會在內部進行一系列的調整,這些調整對於程式來說是透明的,但是會降低執行速度,所以編譯器...