main() { int i=5,j; j=(++i)+((++i)+(++i)+(++i))*2; printf("%d %d\n",i,j); }

为什么j=59

PS:为了解谜,专门下载了VC6.0,电脑上和VS2010冲突,又换了台电脑才装上。
测试了一下,确实问题很大,release模式结果j=63,debug模式结果j=59

●为什么等于59,对debug模式的exe反编译,发现运算顺序不正常,括号里先算一半,再跳出去执行另一个括号,又跳回来算另一半括号,非常非常变态:
一、先计算++i;++i;++i;
于是,表达式变成(++i)+(i+i+i)*2
二、再算i+i;
于是,表达式变成(++i)+(16+i)*2
三、再计算++i;
结果,表达式变成j=9+(8+8+9)*2=59!

●反汇编代码如下(已简化,用i和j变量看起来直观)
mov [i], 5
mov [j], 0
mov eax, [i] //eax=5,计算++i
add eax, 1 //eax=6
mov [i], eax //i=6

mov ecx, [i] //ecx=6,计算++i
add ecx, 1 //ecx=7
mov [i], ecx //i=7

mov edx, [i] //edx=7,计算++i
add edx, 1 //edx=8
mov [i], edx //i=8

mov eax, [i] //eax=8,计算8+8
add eax, [i] //eax=8+i=16

mov ecx, [i] //ecx=8,计算++i
add ecx, 1 //ecx=9
mov [i], ecx //i=9

add eax, [i] //eax=16+9=25,注意,i+i+i是怎么变成8+8+9的
mov edx, [i] //edx=i=9
lea eax, [edx+eax*2]//eax=9+25*2=59
mov [j], eax //j=59
mov ecx, [j]
push ecx
mov edx, [i]
push edx
push offset Format ; "=%d,j=%d\n"
call _prntf

感想,我们到底是为了研究C语言呢,还是要研究编译器?感觉这种源代码不是用来阅读的,而是用来解谜。 决定了,以后学习C语言坚决抛弃++操作符。

附:思考题,VC++6.0的debug模式中,在i=5的前提下,为什么
j = (++i) + (++i) + (i++) + (i++); // j = 28
j = (i++) + (i++) + (++i) + (++i); // j = 23
j = (i++) + (++i) + (i++) + (++i); // j = 25
温馨提示:内容为网友见解,仅供参考
第1个回答  2011-08-07
j不是59啊,应该是63,
++i先加再赋值
从左向右++i,6
++i 7
++i 8
++i 9
i的值为9 再做运算:63
第2个回答  2011-08-07

...i=5,j; j=(++i)+((++i)+(++i)+(++i))*2; printf("%d %d\\n",i,j...
于是,表达式变成(++i)+(i+i+i)*2 二、再算i+i;于是,表达式变成(++i)+(16+i)*2 三、再计算++i;结果,表达式变成j=9+(8+8+9)*2=59!●反汇编代码如下(已简化,用i和j变量看起来直观)mov [i], 5 mov [j], 0 mov eax, [i]\/\/eax=5,计算++i add eax, 1\/...

main() { int i=5,j; j=++i+i++; printf("i=%d,j=%d\\n",i,j); }...
++i 是先加1,再去参加运算,如 i = 1,a=++i;那么执行语句后,a = 2,i=2 i++是先运算,再加1,如 i = 1,a=i++;那么执行语句后,a = 1,i=2 ++是2级运算符,+是4级,所以++高于+,也就是先算++,在算+!

...i=5,j,k; j=i+++i+++i++; k=(++i)+(++i)+(++i); printf(“i=%5d...
应该是11,15,31

...{ int i=5; printf("%d",(++i)+(++i)+(++i)); } 为会输出的是22...
(++i)+(++i)+(++i); 结果是8+8+8=24 vs下面应该是先evaluation第一个++i和第二个++i这个时候i=7 7+7=14 然后evaluation第三个++i这个时候i=8 14+8 =22 和unix下的结果完全不一样 所以这样写是危险的

是C语言、我好笨求解!就是i=5;j=(++i)+(++i)+(i++);然后输出等于i=8...
++i由于++前置,所以先自加再参与运算第一个++i后i变成6,然后第二个++i后i变成7,然后i++的时候由于后置,所以先参与运算,然后再自加,所以这个式子就变成了7+7+7=21,然后算完以后i再自加1,所以i就变成8了。

...main() {int i=5,j=5,p,q; p=(i++)+(i++)+(i++); q=(++j)+(++j...
表达式求值顺序不同于运算结合性和优先级,q=(++j)+(++j)+(++j);这个式子没有顺序点,而++j和q=xxx这些操作都是有副作用(side-effect)的,而副作用的顺序不被保证(这是为了方便各编译器能自行优化代码)。所以最多只能保证执行完以后j=8,而q的值可能由于各编译器优化不同而产生不同结果,...

...void main () { int i=5, j=5, p, q; p=(i++)+(i++)+(i++); q=...
得到这样的解释:对于多个++j这样形式的式子,编译器是这样执行的。理论上是先+,再引用,应该得到这样的结果:6+7+8+9+10……,但编译器不知道按什么原理,第一个数要与第二个相同才能得到结果。我是增加++j的个数发现这个规律的。知道这个规律后,只能加以应用了。没道理可讲吧,呵呵。

...{ int i=3,j; j=(++i)+(++i)+(++i); printf("%d %d\\n",i,j...
不应该啊 怎么会是16, 结果为15 不是Y而是J 的 值 你可以分开看 4+5+6

int i = 5,k; k =(++i) + (++i) +(++i); printf(“%d,%d”,k,i...
造成这个结果的原因就是编译器导致的,在java里面这个结果是 21 8 在vs里面结果是 24 8 这里就需要考虑运算符优先级的问题,按道理说应该是括号优先级最高,所以先运行括号里的运算,从左向右也就是变成三个8相加,你的估计是vc6.0吧,说实话这个22的运算逻辑实在是令人难以理解 ...

i=5 J=(++i)+(++i)+(i++) 怎么算 C语言中的
i=5意思是i的赋值是5,J=(++i)+(++i)+(i++) ++i是先求出i的值,i再+1,i++是先算i+1的值 我也是初学者,不对的话请谅解 如果需要补充的 请告诉我 我正在学习

相似回答
大家正在搜