變數的儲存地址分配和函式返回區域性變數相關問題
當一個函式執行完後,內部的區域性變數會被銷燬,因此,在返回函式值時,不要返回區域性變數,否則會出現不知名的錯誤。但是,有的時候又是可以返回區域性變數的,這又是為什麼呢?
來看一下這個例子:
假如定義了一個如下的結構:
struct LIST{
int a;
int b;
};
定義一個函式:
struct LIST make1(int x, int y){
struct LIST temp;
temp.a = x;
temp.b = y;
return temp;
}
使用如下語句進行賦值:
Int *p = make(1,2);
執行結果如圖:
結果正確!!! 不是說不能返回區域性變數嗎?為什麼這裡能得到正確的結果呢?
仔細分析,我們發現,雖然函式make1裡的temp是區域性變數,將隨著make1的結束而撤銷,但是在make1結束時,temp裡面的資料已經作為函式值返回了,與temp的撤銷無關。因此,如果只是返回值的話,即使返回區域性變數,那麼最終還是會將正確的值傳到相應的變數。再看下面一個例子:
char *func(){
char a[] = "1234";
return a;
}
char *p;
p = func();
printf("%s", p);
執行結果:
輸出的與a陣列中的字串完全不一樣!!! 因為陣列作為區域性變數,當函式結束後,陣列便被銷燬。
int *func(){
int a = 2;
return &a;
}
int *p;
p = func();
printf("%d\n", *p);
執行結果是
!!!仍然是2 !!!不是說內部變數會被銷燬嗎?為什麼p指向地址儲存的值還是2!!!
原來編譯器在函式執行結束後,的確會對區域性變數進行銷燬,但是需要一定的時間。例如以下程式碼:
最終,執行的結果是:
結果正確。
下面再看一個例子:
struct LIST *make2(int x, int y){
struct LIST *temp;
temp = (struct LIST*)malloc(sizeof
temp->a = x;
temp->b = y;
printf("變?量?內ú部?地?址·%ox\n",temp);
printf("變?量?內ú部?地?址·%ox %ox\n",&temp->a, &temp->b);
printf("變?量?在ú內ú部?地?址·的?值μ:阰%d %d",*(&temp->a),*(&(temp->b)));
return temp;
}
struct LIST *p = make2(1,2);
printf("\n變?量?外猘部?地?址·:阰%ox\n", p);
printf("變?量?在ú內ú部?地?址·的?值μ:阰%d %d\n",*(&p->a),*(&(p->b)));
printf("%d %d\n", p->a, p->b);
執行結果為:
在函式裡面定義了局部指標,但最終的值還是不變!!!這又是為什麼呢?
原來,有malloc申請的記憶體是存放在堆中,因此,在函式結束後並不會被銷燬!!!
現在複習一下C語言中變數的儲存地址分配。
儲存區可以分為:
- 程式碼區:用來存放程式的二進位制程式碼
- 文字常量區:存放字串常量
- 全域性區(靜態區):用來存放全域性變數和靜態變數
- 堆:一般由程式設計師分配和釋放。
- 棧:編譯器自動分配和釋放,存放函式的引數,區域性變數等。