2013-02-15 63 views
0

在下面的代碼中,我希望tmp字符數組在f()返回後被銷燬,因此x根本不應該被打印。函數返回後字符數組未被破壞

但是,在下面的函數x獲得打印在main()但for循環不打印正確的東西。有人可以解釋這種行爲。這是輸出。

ABCDEFG 一個 b Ç d Ë ˚F 克 ABCDEFG ?

ķ Ÿ 我

#include <iostream> 
using namespace std; 

char* x; 
void f() 
{ 
    char tmp[100]= "abcdefg"; 
    x = tmp; 

    cout << x << endl; 
    for(int i=0; i < 7; i++) 
     cout << x[i] << endl; 
} 

int main() 
{ 
    f(); 

    cout << x << endl; 
    for(int i=0; i < 7; i++) 
     cout << x[i] << endl; 
} 
+0

定義「破壞」。 tmp在堆棧上創建。如果您在調用f()之後調用另一個方法,可能會覆蓋tmp,否則編譯器沒有理由重寫堆棧來整理事情。但是,你正在做的事情被認爲是危險的。 – Pete 2013-02-15 15:22:40

+1

請選擇C或C++。 – 2013-02-15 15:23:02

+0

什麼是「我是」? – banuj 2013-02-15 15:23:56

回答

1

要調用未定義的行爲。 f()範圍關閉後,指針可能有效也可能無效。

+0

,它解釋了cout << x,但是for循環中的打印字符不打印相同的字符數組。 – Pungs 2013-02-15 15:24:52

+0

你正在做很多被認爲是不好或明顯錯誤的事情。介意說明原因是什麼? – 2013-02-15 15:25:56

+0

@Pungs是的,因爲堆棧中的位置已被另一個數據替換,所以當您執行了'cout << x << endl;'此代碼將堆棧中的數據替換爲其他數據,這些數據不可打印 – banuj 2013-02-15 15:26:47

0

您正在調用UB。您訪問不再爲您的程序分配的內存。這僅僅是運氣它在第一印刷品上運作。

3

你在做什麼是未定義的行爲,你有一個指向一個內存位置的指針可能會或可能不會。這不好。

實際發生的是你的char buffer tmp位於函數f()的堆棧幀上,當該函數返回數據時,堆棧上的數據將被未來的堆棧幀覆蓋。

做你所做的事情的正確方法很簡單。

std::string f() { 
    std::string str ("abcdefg"); 
    std::cout << str << '\n'; 
    return str; 
} 
int main() { 
    std::string s=f(); 
    std::cout << s << '\n'; 
} 
0

在程序x被定義爲一個全球性的指針作爲char temp[100]是在棧上分配的,其與棧上的地址進行初始化。當函數f返回時,堆棧指針遞減。但是,x將繼續指向相同的內存位置,該內存位置將不具有正確的值,因此會觀察到錯誤的輸出。