簡體   English   中英

在C中的while循環條件中使用賦值運算符

[英]Using the assignment operator in a while loop condition in C

問題是:

以更易讀的方式重寫以下C代碼:

while (*dst++ = *src++);

我想檢查一下我是否正確理解了這一行。 通過將* src分配給* dst,它檢查* dst(並且,通過擴展名,* src)是否為非零(或零)值。 如果非零,則執行while主體,否則跳過它。

基於以上理解,我的回答是:

*dst = *src;
while (*dst) {
   [do stuff]
   *dst++;
   *src++;
   *dst = *src;
}

我意識到兩個變量的后增量位置對於實際程序很重要,但我認為這並不重要。

是的,這正是在單行代碼上完成的工作( char與空終止符一起復制)。 但是在你的代碼中

*dst++;
*src++;

可以替換為

dst++;
src++;

不必要地取消引用它

為了進一步解釋,分配的值是在while條件中檢查的賦值表達式的值,當轉換為\\0終止循環,但是也在dst復制\\0

您編寫的實現也會執行一次檢查和一次分配,即使它是空字符串就像原始字符串一樣。

在你的情況下是的,后增量或預增量並不重要,但在原始實現中它確實如此

我的意思是最后一行, ++dst;++src; dst++;src++; 你的情況下。

但是在最初的實施中如果你已經使用過

*++dst = *++src

對於復制而言,這是錯誤的,毫無意義的。 想想它是空字符串的情況。 您將訪問數組索引超出范圍。


 while(*dst++ = *src++); 

這是可讀的 - 事實上,對於您編寫的第二個代碼,我必須考慮邊緣情況的兩倍 - 這里是簡潔的簡單邏輯。 減少代碼減少混淆。 可讀性並不意味着更多的代碼 - 更干凈的代碼更具可讀性。

您可能知道,原始循環是用於復制以零結尾的字符串的常見C語言。 任何C程序員都應該一目了然。 所以在這個意義上它已經非常可讀了。

修改后的版本更難理解,循環外部和內部重復分配。

如果你想以盡可能詳細的方式逐步寫出來,同時也保持與原始行為完全相同的行為,我建議這一點,假設srcdstchar*指針。

// This extra pair of curly braces keeps the `char c` local to this code
{
    char c;  // Change this if the type is different
    do {
        c = *src;
        *dst = c;
        src = src + 1;
        dst = dst + 1;
    } while( c );
}

順便說一下原來的一個問題是許多現代C編譯器會對賦值發出警告,這個想法可能是對於預期的==比較可能是一個錯字。 您通常可以使用一組額外的括號來抑制此警告:

while(( *dst++ = *src++ )) ;
   *dst++;
   *src++;

和...一樣

   *dst; <<dereferencing for no use. 
    dst++;  
   *src; <<dereferencing for no use.
    src++;

通過將* src分配給* dst,它檢查* dst(並且,通過擴展名,* src)是否為非零(或零)值。 如果非零,則執行while主體,否則跳過它。

這是正確的,但就這些代碼的目的而言,它錯過了重點。 代碼功能的高級描述是:將src指向的數組的連續元素復制到dst指向的數組的連續元素,直到復制了值為0的元素。 特別是,如果srcdst是指向char指針,那么這是strcpy()函數的可能實現。

但是你的表征並沒有描述代碼的所有影響,包括將srcdst指針遞增到復制的最后一個元素之后的一個位置。 您的版本與此不符。 此外,您的版本在執行指針增量方面有點奇怪,因為在執行增量之后,它無意義地取消引用新指針值並忽略結果。 不是好風格。

有許多替代方案我認為更具可讀性,但您的教練可能正在尋找一些特定的特征。 我首先要求他們想要一個不在布爾上下文中使用賦值表達式的版本。 我想他們也希望看到指針取消引用和指針增量在單獨的表達式中執行。 這是一個具有這些特性的版本,它產生原始代碼的所有副作用,並最大限度地減少代碼重復:

do {
    *dst = *src;
    dst++;
    src++;
} while (*(src - 1));

你對循環的作用的理解是正確的,但不是你理解后增量,后增量的優先級高於*,所以在原始的while循環中,后增量會增加指針(返回原始值) ,然后取消引用那些將原始* src分配給原始* dest的指針。

我建議將它作為for循環(雖然原來已經非常慣用):

for( ; *dst = *src; ++dst, ++src)
{ }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM