2010-08-02 52 views
2

有人請解釋一下我爲什麼C,而循環進入

int i=0,j=10; 
    while(j>0,i++){ 
    printf("%d%d",i,j); 
    j--; 
} 

將無法​​正常工作和

int i=0,j=10; 
while(i++,j>0){ 
    printf("%d%d",i,j); 
    j--; 
} 

作品。

也請告訴我爲什麼

int i=0,j=10; 
while(j>0,++i){ 
    printf("%d%d",i,j); 
    j--; 
} 

給出了一個無限循環?

感謝和問候

+0

這是完全不可讀的....請使用標記標記在您的處置... – 2010-08-02 17:33:56

+0

即使(j> 0,++ i){}甚至可以編譯? – DixonD 2010-08-02 17:34:27

+0

「while(j> 0,i ++)」不編譯! – Vishal 2010-08-02 17:35:04

回答

16

在您使用逗號運營商,評估其參數和返回第二個你while循環狀態。所以在你的例子中:

while(j>0,i++) - returns i before it gets incremented; 
       that is 0, so loop won't execute at all 

while(i++,j>0) - returns (j > 0) - runs as expected 

while(j>0,++i) - returns i - will run until i overflows max int value 
+1

第一個立即退出 - 與#3不同。否則正確。 – 2010-08-02 17:39:03

+0

是的,你是對的,修正了 – Vladimir 2010-08-02 17:40:12

+2

請注意,在最後一個例子中,在'++ i'溢出的地方循環不一定*退出 - 行爲變得不確定。 – caf 2010-08-02 21:23:51

4

請閱讀C comma operator。基本上,這取決於逗號運算符返回逗號右側的結果 - 因此,在第一個示例中,i ++返回0,循環結束。在第三種情況下,++ i從來不是0(至少不是很長時間),所以你得到了無限循環。中間情況是好的,因爲j>0的結果是從逗號運算符返回的,並且您的循環按預期工作。

+0

我看到這是如何工作的,但是這種用法在c中會被認爲是一種「良好實踐」嗎?似乎有點模糊。 – 2010-08-02 17:42:14

+0

絕對不是。誰在正確的思想中使用逗號運算符的條件? – Yuji 2010-08-02 17:46:18

+0

您鏈接的頁面表明最常見的用法是在for循環中,儘管作者給出的例子比這裏顯示的while循環更加模糊。很難判斷'for'循環的每個部分實際返回哪個語句。 – 2010-08-02 17:48:38

1

您正在使用逗號運算符。逗號運算符的結果是第二個子表達式。所以j>0,i++評估爲i++i++最初爲0,所以循環從不執行。

同樣,j>0,++i的計算結果爲++i,在溢出之前它將不爲零,所以它似乎永遠循環(雖然真的只是很長一段時間)。

i++,j>0因爲最後一個子表達式是j>0,這是您想要的實際條件。請注意,儘管逗號運算符會拋出第一個表達式(在本例中爲i++)的結果,但它仍會計算該子表達式,因此您仍然會得到副作用(遞增i)。

0

在這些情況下,您有包含逗號運算符的表達式。逗號運算符評估其左操作數,然後評估其右操作數。結果是右操作數的結果。

目前,我們只考慮你的最後一個問題:

int i=0,j=10; 
while(j>0,++i){ 
    printf("%d%d",i,j); 
    j--; 
} 

這不是真的應該一個無限循環,雖然它可能只運行比預期更長的時間。由於逗號運算符的結果是操作數的結果,因此它正在等待++i變爲0.由於它從0開始,因此它將在終止之前循環所有可能的值int。使用16位int,這可能需要幾分鐘時間。用32位的int,它會花費更多的時間相當於。使用64位int,它爲任何實際目的的無限循環 - 我敢肯定,我會死在很久之前,它可能希望以任何速度完成...

+0

它將運行至少直到'我'等於'INT_MAX' - 在這一點上,'++ i'溢出,這導致未定義的行爲。這意味着* anything *是可能的,包括一個無限循環('++ i'可能會使'i'保持不變!)。 – caf 2010-08-02 23:45:52

+0

@caf:從理論上講,確實如此。事實上,你不可能看到這樣的東西 - 雖然有硬件來提供飽和整數,但我從來沒有見過任何人將它用於普通的'int'。鑑於簽名和未簽名變體之間所需的相似程度,以及'unsigned'wrap modulo 2^N-1的要求,我不確定甚至有硬件可以這樣做,儘管這在理論上是可行的。 – 2010-08-03 00:09:29

+0

那麼,飽和功能將會是「ADD」操作的一個屬性 - 您可以想象一個既提供了「Add-With-Saturate」和「Add-With-Wrap」指令的架構,也包含使用前者的C編譯器簽署加法和後者簽名。更有可能是溢出陷阱 - 如果通過跳過陷印指令來處理陷阱,那麼它也會產生飽和效應(儘管程序中止更有可能)。 – caf 2010-08-03 02:26:34