最近在課堂上聽到老師講了C語言中的記憶體配置,感覺挺深刻的,於是就寫下來,當做是對自己的提醒!
微機原理的知識告訴我們,記憶體大致可以分為三部分:代碼區 、堆棧區、資料區段(我的電腦學的不好,按照自己的理解)。C和C++中有全域變數,靜態變數以及局部變數等幾類。全域變數和靜態變數是在編譯的時候就已經分配好在資料區段,也就是說在執行main函數之前就已經分配好了地址,如果定義的時候認為初始化,那麼就存放初始化的值,如果沒有初始化,則由編譯器初始化為0。這就說明在整個程式的執行過程中全域變數和靜態變數的地址和類型不會發生變化,可能變化的只是他的值。
對於動態變數,則在編譯的階段並不分配記憶體,而是執行到相應的程式碼片段時再分配記憶體。局部變數共有以下幾種:
1 int main(void)
{
int a;//局部變數定義於main中;
...........
{
int a;//局部變數定義於程式碼片段內;
}
}
2 void fun()
{
int a;//局部變數定義於普通函數內;
...
}
3 void fun(int a,int b)//形式參數
{
...
}
編譯器對局部變數的處理是放入棧中,學過微機原理知道,出棧和入棧操作的運算元都是跟著指令,存在於程式碼片段內的,當函數執行到局部變數出,進行入棧操作,給他分配棧中的記憶體,供其它操作訪問。在使用結束後再出棧。所以,局部變數的生存期是從定義的地方到該函數結束和程式碼片段結束。
對應情況1第一個,在main函數結束時出棧,第二個在{}內的代碼執行結束後出棧。這也很好理解,函數的調用本身就涉及到對指令地址的入棧操作,調用結束後涉及到指令地址的出棧操作:類比一下如下函數的棧活動:
void fun1(int a)
{
int b;
}
main()
{
int a;
fun1();
}
過程:執行到main函數,對CPU IP的指標入棧:入棧1,保護現場環境(這裡簡化入棧操作) 給局部變數a入棧分配棧記憶體:入棧2。執行fun1(),對CPU IP的指標入棧:入棧3,保護現場。給形參a入棧,分配棧記憶體,入棧4,給局部變數b分配棧記憶體,入棧5,。執行完函數的調用,恢複現場,對入棧5出棧,對入棧4出棧,對CPU IP出棧,函數調用完畢。然後main函數內執行完畢,對入棧2出棧,對入棧1出棧。至此可以看出局部變數的生存期。