2011-08-30 107 views
6

下面的代碼混淆了我一下:C指針質疑

char * strcpy(char * p, const char * q) { 
while (*p++=*q++); 
//return 
} 

這是strcpy函數的執行剝離。從這段代碼中,我們看到指針p和q被賦值,而不是解除引用,q被賦值給p,直到達到\ 0 char。讓我感到困惑的是while循環的第一次迭代。據我所知,數組的指針指向數組的第一個元素。在這段代碼中,指針在賦值發生之前是增量賦值的(right?),所以從我的理解中,第一個元素永遠不應該被賦值給p(因爲後賦值發生在賦值之前),但它確實存在,我不理解後面的魔法。任何人都足以解釋爲什麼? :-)

由於

+6

你對post/pre的定義似乎是倒退的。 Post =之後,Pre =之前。這裏的後遞增表示第一個字符將被複制,然後指針將遞增。 – Marlon

+0

爲什麼C++標籤(和標題)?這是一個C庫函數。 –

+1

看起來像我的完美有效的C++代碼@Paul。那麼爲什麼不* C++標籤? –

回答

9

因爲++是變量後,它們不會遞增,直到後的表達進行評估。這就是爲什麼它是後增量運算符;預增量是前綴(++ p)。 * ++ p將寫入第二個位置,* p ++寫入第一個位置。

+1

哦SH *** T,我真的需要睡覺:S。謝謝Kevin:S – Davita

1

表達式(* q ++)的右側將在* p ++之前進行求值,並且兩者只會在分配發生後纔會增加。

從右到左閱讀聲明並記住後續增量(q ++而不是++ q)在該行中的其他內容解決後發生。

*q --> dereference q 
= --> assign the value 
*p --> to p 

增加兩者。

這樣做直到q p取q的元素= 0,即它到達空終止符時。

2

p++後遞增指針p。因此p的當前值在p遞增之前由尊敬運算符*運行。

你的推理會一直正確,如果while循環被寫成如下:

while (*++p=*++q); 

在這種情況下,增量將間接引用之前發生。

2

不,增量發生在賦值後。

如果它是*(++p),則指針p將遞增,然後分配。

1

這是一個strcpy函數的剝離實現。從這段代碼中,我們看到指針p和q被賦值,而不是解除引用,q被賦值給p,直到達到\ 0 char。

它恰好相反。在*p處的值被設置爲*q,然後兩個指針遞增。

當您有int foo = bar++時,增量發生在foo設置後。有它發生第一次你會做int foo = ++bar

+1

@Marlon,你爲什麼編輯我的文章?你已經顛倒了意思,這是不正確的。 * p被設置爲* q,而不是相反,除非我有一個完整的腦部放屁和缺少的東西。 – Alex

1

q++價值爲q
++q值是q+1

1

while循環的條件正在執行後遞增。等價地:

while (true) { 
    char* old_p = p; 
    const char* old_q = q; 

    ++p; // or p++; 
    ++q; // or q++; 

    *old_p = *old_q; 
    if (*old_p == '\0') 
     break; 
} 
+0

不完全正確,因爲您的while(* p)正在查看下一個字符,而不是剛剛複製的字符。 – Neil

+0

@尼爾 - 啊,傻了。謝謝你的收穫! – Dawson

2

表達x++++x既具有結果(值)和副作用

結果的表達式x++是當前值x。所述副作用是,x的內容通過1

表達++x結果遞增是x加1的電流值的副作用是與上述相同。

請注意,在評估表達式後,不必立即應用副作用;它只需要在下一個序列點之前應用。例如,給定的碼

x = 1; 
y = 2; 
z = ++x + y++; 

沒有保證的是,表達y++求值之前的x內容將被修改,或甚至之前的++x + y++結果被分配給z(既不=也不+運營商引入一個序列點)。 表達式++x的計算結果爲2,但有可能變量x在分配z之後可能不包含值2。

請務必記住,x++ + x++等表達式的行爲明確爲未由語言標準定義;沒有(好的)方法來預測表達式的結果是什麼,或者在評估之後將包含什麼值x

後綴運算符具有比一元運算符的優先級高,所以像*p++表達式解析爲*(p++)(即,你申請的*操作者表達p++的結果)。同樣,表達式p++的結果是當前值p,所以while (*p++=*q++);不會跳過第一個元素。

請注意,自動增量/減量運算符的操作數必須是左值(本質上,指的是可以讀取或修改存儲器的內存位置的表達式)。表達式x++++x的結果是而不是左值,因此您不能編寫諸如++x++(x++)++++(++x)之類的東西。你可能寫一些像++(*p++)p++是不是一個左值,但*p++是),雖然這可能會讓你任何人讀你的代碼打耳光。