C++中计算顺序问题(补充)

接着上一篇的讨论,上次给吴老师发过去,老师回答的时候顺便提了一下,在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++语法来吗?是不是为了某些需要,每几个运算符的结合来做的?还是还有其它的一些原因。估计这个问题可以请教一下学“编译原理”的。

Copyright © 2005-2006 Solrex Yang. All rights reserved.

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注