函式不能返回區域性指標變數
轉自:http://blog.csdn.net/snakewarhead/article/details/8046673
宣告自動指標變數時,編譯器為其在堆疊區分配記憶體,如果在函式中將另外一個自動變數的地址賦值給自動指標變數,在函式呼叫完畢後,指向堆疊區的棧頂指標將移動到呼叫此函式之前的地址位置,從而使自動變數失去意義,返回的失去意義的地址將會使程式不穩定。
函式返回指標。本來就是一個比較容易出問題的操作。在霍頓的《VC++ 入門經典》一書中,給出了一個很有代表性的例子,如下:
- // Ex5_11.cpp
- #include <iostream>
- using std::cout;
- using std::endl;
- double* treble(double); // Function prototype
- int main(void)
- {
- double num = 5.0; // Test value
- double* ptr = 0; // Pointer to returned value
- ptr = treble(num);
- cout << endl
- << "Three times num = " << 3.0*num;
- cout << endl
- << "Result = " << *ptr; // Display 3*num
- cout << endl;
- system("pause");
- return 0;
- }
- // Function to treble a value - mark 1
- double* treble(double da
- ta)
- {
- double result = 0.0;
- result = 3.0*da
- ta;
- return &result;
- }
兩個輸出語句,一個直接輸出3*5=15.另一個在一個函式中進行了乘法運算,也是5*3,存到result變數中也沒有任何問題。返回這個變數的指標,輸出時再接觸引用。貌似也沒有錯誤。兩條輸出語句似乎都應該輸出15.但事實不是這樣。編譯器會丟擲[Warning] address of local variable `result' returned 這樣一個警告資訊。程式執行後的結果也並非是我們預想的那樣。第二條輸出語句會輸出一個不可預見的值。這是怎麼回事呢?
仔細分析一下,result是作用域在treble函式中的區域性變數。當函式執行結束後。變數result會被析構。其原先佔用的記憶體區域已經被系統回收,可以儲存任何資料。而返回的指向該地址的指標也失去了其原有的意義。因此我們得到這樣一條準則:
永遠不要從函式中返回區域性自動變數的地址。
如果你真的需要這樣操作。你可以在函式的參數列中傳入一個指標變數。然後將需要寫入的資料寫入到該指標變數指向的地址。由於該指標指向的變數,作用域在函式體之外。因此不會在函式結束結束時被回收。
現在回到我們遇到的問題。時間函式localtime就是一個返回指標的函式。返回值型別:tm*
該如何接收這個返回值?當然是宣告一個與之型別相同的變數。
於是你會這樣寫:tm* result;
接下來呢?還用問?賦值嘛。是不是這樣:result=localtime(....);
返回什麼型別,當然要給什麼型別的變數賦值。但是這樣卻發生了我們不想看到的結果。
也許你想到了。就是這個指標!返回的指標在函式結束後不再有效。正確的方法可以是:
tm result;
result = *localtime(....);
也可以是:
tm* result;
*result = *localtime(...);
正確的方法的共同特點是在函式結束前,對返回的指標解除引用。然後用這個數值,為變數或指標指向的記憶體區域賦值。也就是說必須要複製函式的返回值。因為函式體中變數會被析構。
指標是靈活而強大的,避免低階錯誤,明確基本概念。才能讓指標更好的為我們服務
相關文章
- Just for fun——C/C++函式返回區域性變數的問題C++函式變數
- test函式中的區域性變數函式變數
- 十二、變數作用域:區域性變數、全域性變數,函式版名片管理系統—新增函式文件變數函式
- javascript的函式的引數是區域性變數JavaScript函式變數
- 函式(三)作用域之變數作用域、函式巢狀中區域性函式作用域、預設值引數作用域函式變數巢狀
- 巨集_變數_函式_指標_標頭檔案變數函式指標
- 函式之定義及全域性變數&區域性變數&風溼理論函式變數
- 全域性變數與區域性變數變數
- 區域性變數和全域性變數變數
- C語言區域性變數、全域性變數、靜態區域性變數、靜態全域性變數C語言變數
- Java區域性變數與全域性變數Java變數
- java 全域性變數和區域性變數Java變數
- JavaScript —— 區域性變數和全域性變數JavaScript變數
- jmeter全域性變數和區域性變數JMeter變數
- 【c】全域性變數與區域性變數變數
- 指標函式 和 函式指標指標函式
- C#7.0--引用返回值和引用區域性變數C#變數
- javascript基礎(函式與方法的區別,變數作用域,變數和函式的宣告提前,函式作用域)(十五)JavaScript函式變數
- javascript中的作用域(全域性變數和區域性變數)JavaScript變數
- C/C++—— 寫一個函式,它的引數為指向函式的指標,返回型別也為指向函式的指標C++函式指標型別
- python全域性變數與區域性變數Python變數
- 成員變數和區域性變數變數
- 彙編眼中的函式呼叫引數傳遞以及全域性與區域性變數與“基址”函式變數
- JavaScript五:全域性變數&區域性變數;運算子JavaScript變數
- python全域性變數和區域性變數, globalPython變數
- 成員變數和區域性變數的區別變數
- C++程式設計經驗-返回區域性變數的討論C++程式設計變數
- iOS 靜變數static、全域性變數extern、區域性變數、例項變數iOS變數
- Python中的全域性變數和區域性變數Python變數
- js-js的全域性變數和區域性變數JS變數
- Python全域性變數與區域性變數詳解Python變數
- 詳解python 區域性變數與全域性變數Python變數
- 函式指標函式指標
- 指標變數指標變數
- [C++] 成員函式指標和函式指標C++函式指標
- 成員變數、全域性變數、例項變數、類變數、靜態變數和區域性變數的區別變數
- Python的區域性變數和全域性變數使用解惑Python變數
- 【不在混淆的C】指標函式、函式指標、回撥函式指標函式