2016-02-05 28 views
-1
void func(){ 
    int i; 
    char str[100]; 
    strcat(str, "aa"); 
    printf("%s\n", str); 
} 

int main(){ 
    func(); 
    func(); 
    func(); 

    return 0; 

} 

此代碼打印:爲什麼本地數組值不會在函數中被銷燬?

[email protected] 
[email protected] 
[email protected] 

我不明白爲什麼會創建垃圾value([email protected]),爲什麼"aa"不斷追加。理論上,當函數終止時,局部值應該被銷燬。但是這段代碼沒有。

+2

因爲你永遠不會初始化它? –

+0

在'strcat'之前做'str [0] ='\ 0';'。 –

回答

1

要使用strcat()您需要有一個有效的字符串,char未初始化的數組不是有效的字符串。

使之成爲有效的「」字符串,你需要做的這個

char str[100] = {0}; 

這將創建一個空字符串,因爲它只包含終止。

使用strcat()時要小心。如果你打算兩個連接到有效字符串沒關係,如果他們超過2,那麼它不是正確的功能,因爲它的方式。

另外,如果你希望你的代碼工作,在main()代替聲明數組並把它傳遞給函數,這樣

void 
func(char *str) 
{ 
    strcat(str, "aa"); 
    printf("%s\n", str); 
} 

int 
main() 
{ 
    char str[100] = {0}; 

    func(str); 
    func(str); 
    func(str); 

    return 0; 
} 
+1

我還沒有理解你的筆記。你說「超過2」是什麼意思? –

1

沒有什麼標準,指出在堆棧上的數據需要被函數返回時「銷燬」。這是undefined behavior,這意味着任何事情都可能發生。

有些實現可以選擇零寫入到了棧上的所有字節,有些人可能會選擇在那裏寫隨機數據,有些可能會選擇不碰觸它。

這個特定的實現,它似乎並沒有試圖淨化堆棧上的東西。

第一次調用func返回後。堆棧中的數據仍然存在,因爲它尚未被覆蓋。當您在第一次調用之後立即再次撥打func時,str變量恰好位於與之前相同的物理內存中。由於在調用函數中沒有其他的函數調用,所以這個數據在第一次調用時沒有變化。

如果您要調用func的調用之間的其他函數,那麼您很可能會看到不同的行爲,因爲str將包含任何其他函數最後調用的數據。

0

strcat功能裝置來連接兩個strings。所以函數的兩個參數都必須表示字符串。此外,第一個參數被改變。

字符數組可以表示一個字符串,您可以用字符串文字(可能是「空白」字符串文字)初始化它,或者在數組初始化或初始化後隱式指定一個零值。

例如

void func(){ 
    char str1[100] = ""; 
    char str2[100] = {'\0'}; 
    char str3[100]; 
    str3[0] ='\0'; 
    //... 
} 

考慮到與所述自動存儲持續時間的對象不是隱含地初始化。他們有不確定的價值。

至於你的問題

爲什麼本地陣列值沒有在功能上被破壞?

那麼原因是數組佔用的內存沒有被其他函數覆蓋。然而,無論如何,這是未定義的行爲。

0

當你聲明:

char str[100]; 

所有你正在做的是聲明一個字符數組,但它是隨機的垃圾。

所以你有效地追加到垃圾。

如果你這樣做,而不是:

char str[100] = {0}; 

然後你會得到不同的結果,因爲該字符串將是空的開始。每當你用C分配內存時,除非你在分配內存時初始化內存,否則它只會是當時內存中的內存。你不能認爲它會爲NULL並且爲零。

相關問題