2013-06-11 46 views
2

意外移動,實乃指針我做了一個字符串連接功能:字符串用C

void 
strcat(char *s, char *t) 
{ 
    while(*s) 
     s++; 
    while(*s++ = *t++); 
} 

似乎就好了工作:

main() 
{ 
    char *s = "Hello, "; 
    char *t = "world!"; 

    strcat(s,t); 
    printf("%s\n", s); 

    return 0; 
} 

產生Hello, world!預期。但一些不必要的事情也發生了,打印字符串t指向orld!strcat不能改變t。相反,它似乎是字符串已經移動;在strcat後遞減t,然後打印它給出正確的字符串。

什麼移動了字符串? strcat必須是它,但不知道它有什麼問題。

編譯爲tcc版本0.9.26(x86-64 Win64)如果有問題。

+0

請注意,以'str'開始的名字和一個字母總是保留給實現,所以你不應該命名你的新函數。 –

回答

4

這是未定義的行爲:

  • 您寫入分配給一個字符串的空間,
  • 你正在寫過去分配的空間。

爲了進行in-place級聯,目標必須包含足夠的空間以適應級聯的結果。這裏是你如何解決這個問題:

main() 
{ 
    char s[14] = "Hello, "; // 14 is enough to fit Hello, world!\0 
    char *t = "world!"; 

    strcat(s,t); 
    printf("%s\n", s); 

    return 0; 
} 

注意:您可能想改變你的函數的簽名,表明第二個字符串沒有得到修改:

void strcat(char *s, const char *t) 
1

試試沿着多一行:

main() 
{ 
    char *s = "Hello, "; 
    char newStr[256]; 
    strcpy(newStr, s); 

    char *t = "world!"; 

    strcat(newStr,t); 
    printf("%s\n", newStr); 

    return 0; 
} 

否則,你正在修改一個字符串...這是未定義的。目前它正在改變t,但其他編譯器甚至其他嘗試都會產生新的結果。

2

您的變量t及其內容「world!\ 0」在您的其他變量s後面的內存中,其中包含「Hello,\ 0」。您的strcat函數覆蓋變量s中的空終止符,並繼續將內存覆蓋到變量t中。

最初,分配的內存可以被顯示爲「你好,\ 0world!\ 0」 你運行你的strcat功能後,它可以被顯示爲「你好,世界!\ 0 \ 0」最後的空終止從未改變了,但其他一切看起來好像它被移動到左邊,因爲你的strcat函數覆蓋了第一個空終止符。

你的指針t仍然指向它之前的內存位置。由於內存已更改,t處的內容可能會顯示爲「orld!\ 0 \ 0」。

打印時顯示爲「orld!」

當然,這是所有未定義的行爲。這種情況每次都會發生,你不能百分之百地正視,不惜一切代價避免這種情況。