2017-02-21 310 views
0

這裏是一個循環,通過C串向後推移:比較無符號的表達與0

size_t slen = strlen(string); 
for (size_t i = slen-1; i >= 0; i--) { 
    /* do stuff */ 
} 

當我編譯此代碼與gcc -Wall -Wextra -std=c99 -o code code.c,收到這樣的警告:

警告:比較無符號表達式> = 0始終爲真[-Wtype-limits]

在處理此警告時,我將此循環替換爲:

for (int i = (int)slen-1; i >= 0; i--) { 

哪些工作正常,但我想知道如果他們是一種方式來使第一個循環仍然編譯沒有上述警告?當我用-Wextra進行編譯時,似乎只會觸發此警告。

+3

爲什麼要讓第一次循環編譯時沒有警告?警告告訴你,這在邏輯上是不正確的。所以不知道你試圖通過試圖保持不正確的代碼來實現。 – kaylum

+0

@ kaylum只是因爲好奇而好奇。在閱讀更多內容之後,我必須同意您的看法,即不正確的代碼。 – RoadRunner

+1

編譯第一個循環有什麼意義?一個無符號變量總是'> = 0',所以爲什麼還要檢查? –

回答

2

無符號整數不能小於0。這就是「無符號」的意思。所以顯然你的循環永遠不會終止。

相反,你可以使用:

for (size_t i = slen; i-- > 0;) { 

這遞減i之前進行測試,因此該循環的最後一次迭代將與i == 0發生,那麼測試i-- > 0失敗,打破了循環。

Related thread

+0

乾杯@ M.M,你的解釋是有道理的:) – RoadRunner

2

這裏真正的犯罪是你違反了所有循環往前走的規則,即使是那些倒退的規則。循環應該寫成如下:

for (size_t i = 0, e = strlen(string); i != e; ++i) { 
    const size_t ri = e - i - 1; 

    /* do stuff with index ri */ 
} 

這種結構使得對迭代器對反向迭代關係明顯− 1偏移,避免了任何的符號性問題,併爲您提供一個免費的輪計數器。

+0

是的,我想我沒有仔細研究它是如何寫的。感謝您的解釋,但它非常有幫助:)。 – RoadRunner

相關問題