天天看點

傳回局部變量指針

一般我們都知道不能傳回局部變量的指針,但很多人知道其然,不知道是以然,那麼接下來我們分析一下,先看兩段代碼

/*test1.c*/

#include <stdio.h>

char* get_str()

{

    char str[] = {"hello"};

    return str;

}

int main()

    char* p = get_str();

    printf("%s/n", p);

    return 0;

====================

/*test2.c*/

    char *str = {"hello"};

test2.c運作是沒有問題的,也可以列印出正确的值,而test1.c卻是錯誤的,列印出來的值和預期的完全不一樣。他們都是傳回了局部變量的指針,為什麼會有差異呢,我們仔細看代碼,發現他們隻有一個地方不一樣,那就是test1.c 裡面str是一個數組,test2.c裡面str是一個指針。原因就在這,str指針,其值是一個常量,而常量是放在資料段裡面的,即便函數傳回了,資料段裡面的常量資料也還會在,直到程式結束才會消失,是以我們可以列印出來。

而對于數組來說,它是一個局部變量,是放在棧裡面的,函數傳回之後,str指向的空間還是在的,如果我們列印出它的位址還是沒有變。那麼為什麼内容會變掉呢,難道是系統會把棧中的資料清除,答案是否定的,因為這樣做會消耗系統的資源,而且沒有任何好處,下次用到這塊記憶體還是會進行初始化的。列印出來的内容變掉是因為printf本身也是一個函數,也會進行參數的壓棧,在壓棧的過程中會把原來str指向的空間覆寫掉,也就改變了其中的值。如果我們在get_str之後,不調用任何函數并不建立新的局部變量(嚴格的說是不使棧繼續往下增長),這個時候p指向的内容還是沒變的。