while迴圈問題

int main(void){

int m1=123,m2=5;

while(m2 - -){m1%=m2;}

printf("%d\n",m1);

}

請問為什麼會發生執行錯誤,然後沒有輸出結果???

請告知程式的流程,感恩!!

Update:

可是m2=0的時候while(m2- -)不是會判斷為0跳出迴圈了嗎???請指正~~謝謝

Update 2:

的確是我的觀念不好..我一直以為while() { }算是一個連續的式子,

所以while(m2- -){ }應該跑一遍後才做- - 的動作,所以我可以這樣說嗎?

當while(m2- -)必須先以m2值帶入判斷,如果滿足判斷式,{ } 才做- -的動作,

那麼while(- - m2){ }的話,m2應該就是以m2 - -過後的值做判斷,而且滿足的話{ }

同樣以- - 過後的值做運算,也就是說m2判斷式跟運算式是同樣的值,是這樣嗎??

謝謝各位的指教!!

Update 3:

原來這是"序列點"的問題阿!!感謝【帕拉提斯】解惑~

讓我受益良多呢 !!

3 Answers

Rating
  • 其威
    Lv 7
    9 years ago
    Favorite Answer

    因為在 while 迴圈的最後一次,m2 會變成 0,導致 m1 %= m2 會有除以 0 的錯誤。

    m1 = 123, m2 = 4

    m1 = 3, m2 = 3

    m1 = 0, m2 = 2

    m1 = 0, m2 = 1

    m1 = 0, m2 = 0 => 噢歐~

    2011-06-23 23:22:59 補充:

    問題是 m2 = 1 的時候。

    m2 = 1 時,

    m2-- 會將 m2 - 1,然後回傳 -1 以前的值。

    於是 while 會因為 m2-- 回傳了 1 而繼續,可是 m1 %= m2 的時候 m2 已經變成 0 了。

    2011-06-24 19:41:50 補充:

    你可能要加強理解有關「序列點(sequence point)」這觀念。

    所謂序列點就是,當執行到這裡的時候,該敘述的結果已經可以確定,而所有副作用都已經套用至操作。

    例如 f() + g(),C/C++ 不保證 f() 還是 g() 哪個會先執行,但是在做 + 的之前會保證 f() 與 g() 都已經執行。

    while 迴圈的控制敘述(就是包在 () 裡面的東西)也是如此,在進入迴圈主體以前,該控制敘述已經完成執行,所有副作用都已經確定。

    2011-06-24 19:43:43 補充:

    以你的例子來說,while (m2--) { m1 %= m2; } 在執行到 m1 %= m2; 的時候,m2-- 已經完成執行,所以使用到的 m2 會是完成 -- 以後的值。

    而 m2 原本的值(-- 以前的值)只有在 while 的判斷式中有效。

    也就是說,在判斷迴圈該不該繼續時候,是使用前值 1,但是進入到迴圈主體以前,-- 已經完成操作,所以接下來 m1 %= m2; 的 m2 會是 0。

    2011-06-26 07:37:41 補充:

    我想,發問者應該是以為 while (m2--) { ... } 這東西,在判斷與迴圈主體中會使用 m2 的前值,一直到迴圈主體結束以後才會 --。

    所以,他會很奇怪為什麼 m1 %= m2 會發生 /0 的狀況。

    不是說我的答案比較好或是你的答案不對,應該只是你沒想到(事實上我們一開始都沒想到)發問者會搞不清楚到底 -- 的指派動作在何時發生。

    所以我覺得這是序列點問題。

    如果不用「序列點」這名詞,應該用什麼名詞表示「到此為止程式碼的副作用都已套用、程式的狀態可以確定」的點?

  • 9 years ago

    就回答

     本問先後

     補問先後

     是否指出問題所在

     初學者是否易懂

    等,個人都覺得:

     該選東邪。

  • 9 years ago

    問題出在迴圈的最後一次,

    m2=1, while 的條件成立,進入迴圈,

    問題在此時發生了!

    m2-- 會讓m2減一,m2變成 0,

    接下來的m1%=m2 當然會發生「除數為0」的錯誤。

    請試著做以下的修正:

    while(m2 - -) {m1%=m2;}

    改成

    while(m2) {m1%=m2; m2--}

    便可避開上述的錯誤了!

    2011-06-24 01:15:43 補充:

    >可是m2=0的時候while(m2- -)不是會判斷為0跳出迴圈了嗎???

    錯誤是發生在 m2=1 時!

    看來你對這個 m2-- 的觀念有點混淆,有待澄清。

    m2-- 是後置遞減,

    執行這個指令時,會先取m2,等這個指令結束,進入下一個指令之前才會做減一的動作。

    當m2=1, while (m2--) 在判斷條件時,m2仍是 1, 條件為真,故繼續迴圈。

    此時,m2才做減一的動作,m2變成 0,

    接下來的 m1%=m2 當然會造成除數為零的錯誤!

    2011-06-24 10:53:50 補充:

    簡言之,

    while(m2--) 這樣的用法,

    會讓「進入迴圈主體時的m2」 比 「 while 判斷時的m2」少一。

    2011-06-24 20:35:18 補充:

    如果你改成 while( --m2 ){ }的話,

    「用來做while判斷的m2」和「進入迴圈主體時的m2」便是同樣的值。

    那麼就不會產生目前的錯誤了!

    2011-06-25 22:42:06 補充:

    底下是發問者的評價:

    「兩位大大真是讓我很煩惱呢-..-

    也非常感謝 東邪無弓 大大的解惑,因為【帕拉提斯】直接點出我的問題所在所以先給他囉!!非常非常感謝兩位 XD」

    發問者要如何抉擇,是一回事,可以尊重。

    但評價悖離事實又是另一回事了!

    提醒提問者好好比對發言的時間序列和發言內容,是誰先點出問題的癥結!

    再提示一點:這也不是單純用「序列點」可完全涵蓋的!

    (雖然我自始至終從不提這個名詞!)

    2011-06-26 18:57:01 補充:

    「序列點」雖是編譯學理最基本的ABC,

    但套用至極簡單的 while(m1--) 指令,且對此指令都會混淆的初學者身上,

    我敢說,要花更多時間去解說何謂「序列點」,

    只是這個初學者也迷迷糊糊的能混過就算了!

    「見人說人話,見鬼說鬼話。」,只是人鬼混淆了!

    怎麼辦?直接列入黑名單便是了!

Still have questions? Get your answers by asking now.