[問題] n++ ++n 的問題

看板C_and_CPP作者 (苦力)時間14年前 (2010/03/26 16:22), 編輯推噓14(14048)
留言62則, 18人參與, 最新討論串1/1
#include <stdio.h> #include <stdlib.h> void main(int argc,char **argv) { int n=4; printf("%d,%d,%d,%d,%d\n",n,++n,n,--n,n); } ----------------------------------------- 為什麼輸出結果是 4,4,4,4,4 而不是 4,4,3,3,4 如果是學校老師教的4,5,5,4,4 我的compiler 環境是 gcc (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu3) -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 203.75.230.80

03/26 16:25, , 1F
為什麼還是有老師教這種問題-_-"
03/26 16:25, 1F

03/26 16:28, , 2F
置底十二誡之九
03/26 16:28, 2F

03/26 16:28, , 3F
這是C/C++語言標準未定義的行為,所以各家compiler 表現不同
03/26 16:28, 3F

03/26 16:35, , 4F
推1F, 為什麼還是有老師教種問題, 而且大家題目都很像!?
03/26 16:35, 4F

03/26 16:53, , 5F
看到標題就很興奮,這不是我之前才加進去的十誡嗎 XD
03/26 16:53, 5F

03/26 17:10, , 6F
這種題目大概是申論題吧XD,要學生根據結果去討論
03/26 17:10, 6F

03/26 17:11, , 7F
各編譯器是用什麼方法來解決這種未定義的行為XD
03/26 17:11, 7F

03/26 17:13, , 8F
不過有幾個老師會在上課講出「未定義行為」呢...XDD
03/26 17:13, 8F

03/26 17:14, , 9F
我遇過的老師是 "考" 這個作為評量學生程式能力的標準 Orz
03/26 17:14, 9F

03/26 17:21, , 10F
研究所入學考試的確有考類似問題XD
03/26 17:21, 10F

03/26 17:54, , 11F
推申論題 XD
03/26 17:54, 11F

03/26 18:52, , 12F
跟老師說101沒加蓋
03/26 18:52, 12F

03/26 20:54, , 13F
為什麼這段程式碼我好像上課也看過@@
03/26 20:54, 13F

03/26 21:47, , 14F
真無言 到處都有這樣的腦X亂出題
03/26 21:47, 14F

03/26 22:45, , 15F
可以問一下是哪邊的老師嗎?
03/26 22:45, 15F

03/27 00:37, , 16F
很無聊的問題 誰會寫這種爛程式
03/27 00:37, 16F

03/27 02:19, , 17F
雖是未定義行為 但我腦袋的compiler 出來的答案跟老師一樣耶
03/27 02:19, 17F

03/27 03:59, , 18F
我也想知道尊師芳名
03/27 03:59, 18F

03/27 05:47, , 19F
這不算是爛程式.該解釋的應該要解釋清楚,未定義也要講.
03/27 05:47, 19F

03/27 06:26, , 20F
把The C Programming Language拿來搜尋undefined,找不到有關
03/27 06:26, 20F

03/27 06:26, , 21F
這個的未定義行為. 有人知道出處嗎?
03/27 06:26, 21F

03/27 06:54, , 22F
找到了,ISO/IEC9899 6.5.2.2 第10段指出unspecified行為
03/27 06:54, 22F

03/27 06:55, , 23F
是沒有規定function call參數處理順序,而不是沒定義.
03/27 06:55, 23F

03/27 08:57, , 24F
undefined 是因為它進入 printf 之前會先對五個 n 求值
03/27 08:57, 24F

03/27 08:58, , 25F
其中 ++n --n 對記憶體修改了兩次, 但卻沒有 sq 把它們隔開
03/27 08:58, 25F

03/27 21:11, , 26F
不對啊,標準文件上說是unspecified不是undefined.
03/27 21:11, 26F

03/27 21:11, , 27F
要說"undefined"之前請在字意上多斟酌考慮一下
03/27 21:11, 27F

03/27 21:12, , 28F
如果是"undefined",你連它處理的過程都講不出來.
03/27 21:12, 28F

03/27 21:58, , 29F
參數求值順序是 unspecified 沒錯, 不過在兩個 seq. point
03/27 21:58, 29F

03/27 21:58, , 30F
之間修改同一個記憶體兩次是 undefined.
03/27 21:58, 30F

03/27 23:08, , 31F
但這能不能列為例外? --n,++n的結果,不管哪個先做,就是n
03/27 23:08, 31F

03/27 23:29, , 32F
結果怎麼會是 n ? 別忘了他有五個 n 這五個順序都不定
03/27 23:29, 32F

03/27 23:30, , 33F
這兩個不見得會連續被估值, 誰先算後算都回影響其他三個 n
03/27 23:30, 33F

03/27 23:40, , 34F
聽你毫洨,這個case怎麼估值最後n都一樣.
03/27 23:40, 34F

03/27 23:40, , 35F
我沒說印出來的狀況,而是指最後的結果
03/27 23:40, 35F

03/27 23:41, , 36F
請注意,是 (--n,++n); //這樣清楚嗎?
03/27 23:41, 36F

03/27 23:44, , 37F
你何不用其它編譯器是看看就知道? VC6 結果是 4,4,3,3,4
03/27 23:44, 37F

03/27 23:46, , 38F
它估完值就把結果 push 到堆疊了, 又不是最後一起 push
03/27 23:46, 38F

03/27 23:46, , 39F
跟你說不是前面五個n而是考慮兩個n,是眼睛狗到蛤肉啊?
03/27 23:46, 39F

03/27 23:47, , 40F
如果只考慮 ++n,--n 他本來就是有定義的, 有什麼好爭的?
03/27 23:47, 40F

03/27 23:48, , 41F
在這種情況下中間那個是 comma operator 它算個 seq. point
03/27 23:48, 41F

03/27 23:48, , 42F
對啊,我想談的是這個,你卻硬切回前一個seq.point,也是未定義
03/27 23:48, 42F

03/27 23:52, , 43F
ok,在n=2; f(++n,--n);程式,++/--格式上是未定義行為,內容
03/27 23:52, 43F

03/27 23:53, , 44F
我可看成是定義的,可這麼說嗎?
03/27 23:53, 44F

03/27 23:55, , 45F
就我看來它可以是 f(3,2) 或 f(2,3) 除非你知道 f 怎麼做的
03/27 23:55, 45F

03/27 23:56, , 46F
說錯........
03/27 23:56, 46F

03/27 23:57, , 47F
可以是 f(3,2) 或 f(2,1) 結果會是一樣嗎?
03/27 23:57, 47F

03/27 23:59, , 48F
我想到了, 一開始忘了一些規則, 一直無法理解原 po 的結果
03/27 23:59, 48F

03/28 00:00, , 49F
seq. point 到達時, 他才必須完成所有求值, 但他也可提前求
03/28 00:00, 49F

03/28 00:00, , 50F
所以你的範例也可以是 f(2,2) 但很顯然這只是其中一個 case
03/28 00:00, 50F

03/28 00:08, , 51F
被搞到混掉, 好像不能是 f(2,2) 這樣似乎怪怪的, 應是上面
03/28 00:08, 51F

03/28 00:08, , 52F
兩種之ㄧ. 所以原 po 的結果我也覺得奇怪. 是否編譯器發現
03/28 00:08, 52F

03/28 00:09, , 53F
它是 undefined, 就直接給 4 4 4 4 4
03/28 00:09, 53F

03/28 00:22, , 54F
因為變數是int才會有這種不依照堆疊順序的計算
03/28 00:22, 54F

03/28 00:30, , 55F
你們說的例子跑出f(2,2)也是有可能的,
03/28 00:30, 55F

03/28 00:33, , 56F
如果n是自定義類別INT,然後有重載算符++/--,那麼出來的
03/28 00:33, 56F

03/28 00:35, , 57F
結果就會依照堆疊順序去計算。
03/28 00:35, 57F

03/28 01:07, , 58F
如果是自定義型別加多載, 誰先求值仍然是 unspecified 的
03/28 01:07, 58F

03/28 01:09, , 59F
但不會是 undefined 的因為多載函式有 sequence point 隔開
03/28 01:09, 59F

03/28 09:26, , 60F
i=v[i++]到底是 unspecified還是undefined?
03/28 09:26, 60F

03/28 09:33, , 61F
怎麼有人說後來改成undefined...
03/28 09:33, 61F

03/28 12:17, , 62F
不知道,太複雜了~反正兩個順序點之間不要又寫又讀比較好
03/28 12:17, 62F
文章代碼(AID): #1Bh6x7w6 (C_and_CPP)