指向臨時變數的指標的返回

2021-06-21 10:32:55 字數 2487 閱讀 9902

一直以為對於函式返回的指標了解得還可以,但是真實不用不知道,一用嚇一跳。今天在一篇部落格上面看到如下兩段**,部落格的作者給出了乙個問題,但是並沒有解釋為什麼不同。自己通過實驗給出了解釋,但是不知道對不對,僅供參考!

下面是個錯誤的例子:

char* get_str(void)

;return str;

}int main(int argc, char* argv)

下面這個例子沒有問題,大家知道為什麼嗎?

char* get_str(void)

;return str;

}int main(int argc, char* argv)

我在linux環境下面驗證了作者的說法,的確是那樣,上面乙個有錯,下面乙個正確。問題就出在乙個用的是陣列型別,而另外乙個用的是指標型別(從側面亦可以看出並不是有些大學老師說的那樣char str等價於char* str),由於棧裡面的變數都是臨時的。當前函式執行完成時,相關的臨時變數和引數都被清除了。不能把指向這些臨時變數的指標返回給呼叫者,這樣的指標指向的資料是隨機的,會給程式造成不可預料的後果。但是指標卻有所不同,指標的位址在棧上,但是它所指向的內容卻是在堆上面,所以並沒有被清除。這就是為什麼乙個正確乙個錯誤的原因。

其實這部落格提前寫了一天,我並沒有發表,因為怕自己理解得有錯,所以跟部落格的作者寫信交流下了,下面貼出我們的信件內容,希望對需要的朋友有所幫助:

問:

大家都知道,棧裡面的變數都是臨時的。當前函式執行完成時,相關的臨時變數和引數都被清除了。不能把指向這些臨時變數的指標返回給呼叫者,這樣的指標指向的資料是隨機的,會給程式造成不可預料的後果。

下面是個錯誤的例子:

char* get_str(void)

;return str;

}int main(int argc, char* argv)

下面這個例子沒有問題,大家知道為什麼嗎?

char* get_str(void)

;return str;

}int main(int argc, char* argv)

我在linux環境下跑了,對**做了點修改,相應的修改和執行結果如下:

#include

char* get_str(void)

;return str;

}int main(int argc, char* argv)

執行結果:

[root@localhost singnode]# ./ss

97-12

#include

char* get_str(void)

;return str;

}int main(int argc, char* argv)

執行結果:

[root@localhost singnode]# ./cc

9798

對於這樣的執行結果是不是因為指標的位址雖然是在棧上,但是它指向的內容卻是在堆上面,所以並沒有被清除。而陣列的位址和內容都是在棧上面(首位址除外),所以出錯。而對於     printf("%d/n", *p);能夠輸出正確的97,是因為首位址被當成指標來處理了,所以它的內容儲存在堆上面,而其它的值儲存在棧上面則被清除,從而產生了隨機值,如-12。

(在此解釋下我最初的理解,紅字部分,一開始我並不知道陣列返回的p也是正確的值,只是在呼叫printf語句後p的值才被破壞掉了,所以這是我之前根據執行結果來做的解釋,在此糾正下。)

答:

int main(int argc, char* argv)

執行結果:

[root@localhost singnode]# ./cc

9798

對於這樣的執行結果是不是因為指標的位址雖然是在棧上,但是它指向的內容卻是在堆上面,所以並沒有被清除。而陣列的位址和內容都是在棧上面(首位址除外),所以出錯。

答:是的。

而對於     printf("%d/n", *p);能夠輸出正確的97,是因為首位址被當成指標來處理了,所以它的內容儲存在堆上面,而其它的值儲存在棧上面則被清除,從而產生了隨機值,如-12。

答:char* p = get_str();

此時p指向的內容還沒有破壞,你可以在偵錯程式中看一下。

printf("%d/n", *p);

此時因為呼叫了printf,所以p就被破壞了。

printf("%d/n", *(p+1));

即使再呼叫:

printf("%d/n", *p);

結果也是錯誤的。

這是最後寫的回信:

非常感謝!我驗證了下,如下:

(gdb) print p

$2 = 0xbffff703 "dbcd"

(gdb) s

9812      printf("%d/n", *p);

(gdb) print p

$3 = 0xbffff703 "��/017m"

(gdb)

在呼叫printf之前的p內容還沒有被破壞掉,但是呼叫printf之後就被破壞了

指向變數的常指標與指向常變數的指標變數的區別

一 指向變數的常指標 形式 型別名 const 指標變數名 將指標變數宣告為const型,這樣指標變數始終保持為初值,不能改變,即其指向不能改變 例 include include int main 常指標pcpt已經指向了cbuff1,就不能再指向cbuff2了。注意 雖然常指標只能始終指向同乙個...

指向變數的常指標和指向常變數的指標

剛接觸到指標時,關於指向變數的常指標和指向常變數的指標容易混淆,所以整理下,希望能夠幫助自己也幫助到大家。常指標就是我們說的指向常量的指標,顧名思義,它是用來指向常量的。實際上,c 規定只能用指向常變數的指標指向常變數,普通指標指向它就會報錯,原因也很容易理解,我們用普通指標指向常變數之後,有可能就...

返回指向區域性變數的指標或引用

返回區域性變數沒問題 如果返回區域性變數有問題,函式的意義還有嗎?全域性變數還用返回嗎?返回指向區域性變數的指標才有問題 函式退棧之後,區域性變數消失,指標將指向未知區域,所以出現問題。返回區域性變數的引用也是絕對不可以的 引用只是變數的乙個別名,變數本體都不存在了,引用當然也沒有任何意義。還有,如...