2013-05-08 69 views
2

我發現嵌入在C++項目中的以下代碼片段。代碼通過C風格的字符串倒退。當我看到這個時,我認爲這應該導致未定義的行爲。但它似乎很好地工作:爲什麼我在字符串開始處遇到NULL終止字符?

const char * hello = "Hello World."; 
const char * helloPointPos = strchr(hello, '.'); 
for (const char * curchar = helloPointPos; *curchar; curchar--) { 
    printf("%s", curchar); 
} 

我想知道的是*curchar; curchar--的一部分。這假定字符串以\ 0開頭。這是一個合法的假設嗎?這段代碼是否會導致未定義的行爲?如果不是,爲什麼不呢?

如果您能夠對此進行說明,我將不勝感激。 BTW平臺是Windows,編譯器是VC++ 2010.

編輯:謝謝大家的參與。這兩個答案都非常好,幫助了我。但既然我只能接受一個答案,我會去找paxdiablo的答案,因爲它有更多的細節。謝謝!

回答

7

不,它非常不要求字符串前的字符是\0,以便代碼沒有定義的行爲。

事實上,它是加倍未定義,因爲您不允許取消不在數組內的指針或超出結尾的一個字節。由於這是在數組之前引用一個字節,所以在這個意義上它也是無效的。

可能在某些情況下工作(a)但它絕不是好的代碼。

在任何情況下,字符串,而不是字符的打印要給你奇怪的結果:

.d.ld.rld.orld.World. World. 

等。

更好的反向迭代會是這樣的:

char *curchar = &(hello[strlen (hello)]); // one byte beyond 
while (curchar-- != hello)     // check if reached start, post-decr 
    putchar (*curchar);     // just the character, thanks. 

(一)事實上,它往往是約未定義行爲最討厭的事情之一是,它有時確實工作,讓你陷入虛假的安全感。

我經常認爲所有編碼器都應該將電線連接到它們最私密的部分,這樣未定義的行爲可能會產生短暫的劇烈震盪 - 我懷疑會有更少的未定義行爲(或者開發人員少得多)過了一段時間:-)

4

這當然沒有定義的行爲,但在這種情況下,它並不奇怪,它的工作原理。

const char * hello = "Hello World.";將字符串Hello World.放入包含所有其他字符串文字的部分中。所以很有可能,在它之前有一個字符串文字,它以\0結尾,所以\0'在Hello World.之前,並且代碼起作用。

很明顯,你不能依賴它 - 你是字符串可能是該部分的第一個,或者一些非字符串常量可能在那裏。另外,如果字符串是以其他方式分配的話,那麼在低於之前得到\0的機會。

+0

您可以看到下一段代碼中環路條件將失敗的情況示例: \t char * a =「BYE」; \t char * c =「HELLO」; \t *(a + 3)='L'; \t \t 的printf( 「>%d \噸%d \ n」,*( - C), '\ 0'); – 2013-05-08 06:39:38

+0

@PabloFranciscoPérezHidalgo,修改'*(a + 3)'在這種情況下,本身是未定義的行爲('「BYE」是一個常量)。無論如何,我從來沒有說過在一個常量字符串之前保證有'\ 0'。 – ugoren 2013-05-08 13:23:53

相關問題