1. 程式人生 > >變數的儲存地址分配和函式返回區域性變數相關問題

變數的儲存地址分配和函式返回區域性變數相關問題

當一個函式執行完後,內部的區域性變數會被銷燬,因此,在返回函式值時,不要返回區域性變數,否則會出現不知名的錯誤。但是,有的時候又是可以返回區域性變數的,這又是為什麼呢?

來看一下這個例子:

假如定義了一個如下的結構:

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

(struct LIST));

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語言中變數的儲存地址分配。

儲存區可以分為:

  1. 程式碼區:用來存放程式的二進位制程式碼
  2. 文字常量區:存放字串常量
  3. 全域性區(靜態區):用來存放全域性變數和靜態變數
  4. 堆:一般由程式設計師分配和釋放。
  5. 棧:編譯器自動分配和釋放,存放函式的引數,區域性變數等。