C語言中記憶體分配
一、static在C語言裡面可以用來修飾變數,也可以用來修飾函式。
1、 先看用來修飾變數的時候。變數在C語言裡面可分為存在全域性資料區、棧和堆裡。
其實我們平時所說的堆疊是棧而不是堆,不要弄混。
例如:在file.c中
int a ;
int main()
{
int b ;
int *c = (int *)malloc(sizeof(int));
}
a是全域性變數,
b是棧變數,
c是堆變數。
2、static對全域性變數的修飾,可以認為是限制了只能是本檔案引用此變數。有的程式是由許多.c檔案構成。彼此可以互相引用變數,但加入static修飾之後,只能被本檔案中函式引用此變數。
3、static對棧變數的修飾,可以認為棧變數的生命週期延長到程式執行結束時。一般來說,棧變數的生命週期由OS管理,在退棧的過程中,棧變數的生命也就結束了。但加入static修飾之後,變數已經不再儲存在棧中,而是和全域性變數一起儲存。同時,離開定義它的函式後不能使用,但如再次呼叫定義它的函式時,它又可繼續使用,而且儲存了上一次被呼叫後留下的值。
4、static對函式的修飾與對全域性變數的修飾相似,只能被本檔案中的函式呼叫,而不能被同一程式其它檔案中的函式呼叫。
例如:
檔案a.c
static int i; //只在a檔案中用
int j; //在工程裡用
static void init() //只在a檔案中用
{
}
void callme() //在工程中用
{
static int sum;
}
上面的全域性變數i和init()函式只能用在a.c檔案中,全域性變數sum的作用域只在callme()函式裡。變數j和函式callme()的作用域擴充到整個工程檔案。所以可以在下面的b.c中用extern關鍵字呼叫。extern告訴編譯器這個變數或者函式在其他檔案裡已經被定義了。
檔案b.c
extern int j; //呼叫a檔案裡的
extern void callme(); //呼叫a檔案裡的
int main()
{
...
}
而且static會有下面的幾個特點:
1、若全域性變數僅在單個C檔案中訪問,則可以將這個變數修改為靜態全域性變數,以降低模組間的耦合度;
2、若全域性變數僅由單個函式訪問,則可以將這個變數改為該函式的靜態區域性變數,以降低模組間的耦合度;
三、區域性變數和全域性變數
從作用域角度將變數分為區域性變數和全域性變數。它們採取的儲存類別如下:
區域性變數:
①自動變數,即動態區域性變數(離開函式,值就消失)。
②靜態區域性變數(離開函式,值仍保留)。
③暫存器變數(離開函式,值就消失)。
④形式引數可以定義為自動變數或暫存器變數。
全域性變數:
①靜態全域性變數(只限本程式檔案使用)。
②全域性變數(即非靜態的全域性變數,允許其它程式檔案引用)。
從變數存在時間可將變數儲存分為動態儲存和靜態儲存。靜態儲存是在整個程式執行時都存在,而動態儲存則是在呼叫函式時臨時分配儲存單元。
動態儲存:
①自動變數(函式內有效)。
②暫存器變數(函式內有效)。
③形式引數。
靜態儲存:
①靜態區域性變數(函式內有效)。
②靜態全域性變數(本程式檔案內有效)。
③全域性變數(整個程式可引用)。
從變數存放的位置可將變數儲存區分為靜態儲存區和動態儲存區:
靜態儲存區:
①靜態區域性變數。
②靜態全域性變數。
③全域性變數(可被同一程式其它檔案引用)。
動態儲存區:自動變數和形式引數。
CPU暫存器:暫存器變數。
當然,本文討論的對於變數的記憶體儲存分配只是一部分,在C語言中依然會有其他的儲存方式和型別的存在。