在VC6.0中,如果Optimization Switches選擇maximum speed或者minimum size的方式來編譯的話,計算結果b就是9。我試了一下,不管是用release或者debug mode,如果選擇default或者Disables optimizations,結果就是7,如果選擇maximum speed或者minimum size,結果就是9。
本來想反編譯一下看看原理的,可當有優化時,從代碼實在看不出來,debug調了半天也沒有看到哪句是關鍵語句,感覺全是系統調用,只好作罷。
查了下MSDN,說是如果選擇優化的話會有Local and global common subexpression elimination和Automatic register allocation。自動分配寄存器的解釋是:This optimization allows the compiler to store frequently used variables and subexpressions in registers; the register keyword is ignored.鬼知道它怎麼用的寄存器,難不成它在make的時候已經把結果給算出來了?
用VC寫的程序可真大呀,拿這個為例,default是168k(172,083B),maximum speed和minimum size是104k(106,547B)。調程序的時候看到好多系統信息字符串,像service pack 2之類的,還有許多錯誤提醒的程序分支,它好多的工夫放在了對系統的識別和錯誤的處理上了。有感於此就順便看了一下TC的表現:
用TC3.0編譯上個程序,按C++方式,大小:5.96k(6,108B),匯編核心代碼:
:0001.0298 33F6 xor si, si
:0001.029A C746FE0000 mov word ptr [bp-02], 0000
:0001.029F 46 inc si
:0001.02A0 46 inc si
:0001.02A1 46 inc si
:0001.02A2 8BC6 mov ax, si
:0001.02A4 03C6 add ax, si
:0001.02A6 03C6 add ax, si
:0001.02A8 8946FE mov [bp-02], ax
前面0001是反編譯程序後來加上的,本來應該只有後面的偏移量的。TC3.0還是用的16位寄存器,而且只在存儲空間裡保存了b的值,a的值就只用寄存器si了,而且結果明顯也是9。
用TC3.0編譯,不選擇優化,大小:5.99k(6,135B),核心代碼:
:0001.0297 C746FE0000 mov word ptr [bp-02], 0000
:0001.029C C746FC0000 mov word ptr [bp-04], 0000
:0001.02A1 FF46FE inc word ptr [bp-02]
:0001.02A4 FF46FE inc word ptr [bp-02]
:0001.02A7 FF46FE inc word ptr [bp-02]
:0001.02AA 8B46FE mov ax, [bp-02]
:0001.02AD 0346FE add ax, [bp-02]
:0001.02B0 0346FE add ax, [bp-02]
:0001.02B3 8946FC mov [bp-04], ax
如果不選擇優化,則可以看到它給了兩個變量內存地址,但是運算結果還是沒變,仍然是9。
用TC2.01編譯,按C語言方式,大小:4.22k(4,325B),核心代碼:
:0001.01FF 33F6 xor si, si
:0001.0201 33FF xor di, di
:0001.0203 46 inc si
:0001.0204 46 inc si
:0001.0205 46 inc si
:0001.0206 8BFE mov di, si
:0001.0208 03FE add di, si
:0001.020A 03FE add di, si
TC2.0就直接用兩個寄存器si,di,根本不用存儲空間,倒真是干淨。結果顯然也是9。
這樣覺得其實它們做的都對。因為如果按照C++的標准語法,+是Left to right,而Pre-increment“++"是Right to left。按照優先級,()最高,先計算,Left to right,三個括號中計算完了,再計算+,Left to right,然後才是賦值=,Right to left,把值給b。這樣說的話,結果等於7的時候倒是有些違反C++語法了。
就算是把()去掉,因為規定,++與()優先級一樣,也是應該先算三個++,結果還是9。
結論:
看來,這個爭論似乎不是編譯器的問題,而是通常理解的語法與程序規范語法的抵觸。計算機不可能像人一樣具有抽象的推理能力,只能給它先固定好語法的模式,它只按照規范來執行,而不管語義的多樣性。
但是有一個問題是,VC的不優化處理難道不根據C++語法來嗎?是不是為了某些需要,每幾個運算符的結合來做的?還是還有其它的一些原因。估計這個問題可以請教一下學“編譯原理”的。