我是用编译你的代码的,反汇编的结果如下:(局部)
mov [ebp+var_8], 8 //i=8
.text:004113E5 mov eax, [ebp+var_8] //
.text:004113E8 mov [ebp+var_D0], eax //i--之前把i的值保存到,temp[0]=8
.text:004113EE mov ecx, [ebp+var_8]
.text:004113F1 sub ecx, 1 //i--,(从右向左数第一个参数)
.text:004113F4 mov [ebp+var_8], ecx //i=7
.text:004113F7 mov edx, [ebp+var_8]
.text:004113FA mov [ebp+var_D4], edx //i++之前把i保存到:temp[1]=7 (这时候已经执行过i--了)
.text:00411400 mov eax, [ebp+var_8] //i++,(从右向左数第二个参数)
.text:00411403 add eax, 1
.text:00411406 mov [ebp+var_8], eax //i=8
.text:00411409 mov ecx, [ebp+var_8]
.text:0041140C sub ecx, 1 //--i, 无需保存修改前的值,直接改变实参i
.text:0041140F mov [ebp+var_8], ecx //i=7
.text:00411412 mov edx, [ebp+var_8]
.text:00411415 add edx, 1 //++i,
.text:00411418 mov [ebp+var_8], edx //i=8
.text:0041141B mov esi, esp
.text:0041141D mov eax, [ebp+var_D0] //压栈temp[0]=8
.text:00411423 push eax
.text:00411424 mov ecx, [ebp+var_D4] //压栈temp[1]=7
.text:0041142A push ecx
.text:0041142B mov edx, [ebp+var_8] //压栈i=8
.text:0041142E push edx
.text:0041142F mov eax, [ebp+var_8] //压栈i=8
.text:00411432 push eax
.text:00411433 push offset aDDDD ; "%d,%d,%d,%d\n" //压栈字符串"%d,%d,%d,%d\n"的地址
.text:00411438 call ds:printf //调用打印函数,输出8,8,7,8
.text:0041143E add esp, 14h
.text:00411441 cmp esi, esp
.text:00411443 call sub_41113B
.text:00411448 mov esi, esp
可见,++i和--i执行的时候直接改变了i的值,而i++和i--必须在所在的这个语句执行后才能改变i的值,
所以i++作为参数时,实际上先把执行自增前的i值保存起来,i自增,然后用刚才保存的值做参数,是这样的过程,
printf("%d",i++);
相当于下面的语句:
int temp=i;
i=(i+1);
printf("%d",temp);
而++i作为语句一部分时,可以直接改变i,例如
printf("%d",++i);
相当于:
i=(i+1);
printf("%d",i);
因此上面的代码可以翻译为:
int i=8;
printf("%d,%d,%d,%d",++i,--i,i++,i--);
翻译为:(注意:按照调用约定,参数都是从右到左压栈的)
i=8;
temp0=i; //temp0=8;
i--; //7
temp1=i; //temp1=7
i++; //8
--i; //7
++i; //i=8
printf("%d,%d,%d,%d",i,i,temp1,temp0);
所以打印结果是8,8,7,8
另外在TC2.0下面打印结果是:8,7,7,8
而你说你在vc6下面是:8,7,8,8
看来这确实是和编译器有关,三个编译器居然出来的是三个不同结果。而这种代码在实际编程是是不可能写出这么歧义的代码的。。。。。
[[it] 本帖最后由 hoodlum1980 于 2008-2-25 04:52 编辑 [/it]]
mov [ebp+var_8], 8 //i=8
.text:004113E5 mov eax, [ebp+var_8] //
.text:004113E8 mov [ebp+var_D0], eax //i--之前把i的值保存到,temp[0]=8
.text:004113EE mov ecx, [ebp+var_8]
.text:004113F1 sub ecx, 1 //i--,(从右向左数第一个参数)
.text:004113F4 mov [ebp+var_8], ecx //i=7
.text:004113F7 mov edx, [ebp+var_8]
.text:004113FA mov [ebp+var_D4], edx //i++之前把i保存到:temp[1]=7 (这时候已经执行过i--了)
.text:00411400 mov eax, [ebp+var_8] //i++,(从右向左数第二个参数)
.text:00411403 add eax, 1
.text:00411406 mov [ebp+var_8], eax //i=8
.text:00411409 mov ecx, [ebp+var_8]
.text:0041140C sub ecx, 1 //--i, 无需保存修改前的值,直接改变实参i
.text:0041140F mov [ebp+var_8], ecx //i=7
.text:00411412 mov edx, [ebp+var_8]
.text:00411415 add edx, 1 //++i,
.text:00411418 mov [ebp+var_8], edx //i=8
.text:0041141B mov esi, esp
.text:0041141D mov eax, [ebp+var_D0] //压栈temp[0]=8
.text:00411423 push eax
.text:00411424 mov ecx, [ebp+var_D4] //压栈temp[1]=7
.text:0041142A push ecx
.text:0041142B mov edx, [ebp+var_8] //压栈i=8
.text:0041142E push edx
.text:0041142F mov eax, [ebp+var_8] //压栈i=8
.text:00411432 push eax
.text:00411433 push offset aDDDD ; "%d,%d,%d,%d\n" //压栈字符串"%d,%d,%d,%d\n"的地址
.text:00411438 call ds:printf //调用打印函数,输出8,8,7,8
.text:0041143E add esp, 14h
.text:00411441 cmp esi, esp
.text:00411443 call sub_41113B
.text:00411448 mov esi, esp
可见,++i和--i执行的时候直接改变了i的值,而i++和i--必须在所在的这个语句执行后才能改变i的值,
所以i++作为参数时,实际上先把执行自增前的i值保存起来,i自增,然后用刚才保存的值做参数,是这样的过程,
printf("%d",i++);
相当于下面的语句:
int temp=i;
i=(i+1);
printf("%d",temp);
而++i作为语句一部分时,可以直接改变i,例如
printf("%d",++i);
相当于:
i=(i+1);
printf("%d",i);
因此上面的代码可以翻译为:
int i=8;
printf("%d,%d,%d,%d",++i,--i,i++,i--);
翻译为:(注意:按照调用约定,参数都是从右到左压栈的)
i=8;
temp0=i; //temp0=8;
i--; //7
temp1=i; //temp1=7
i++; //8
--i; //7
++i; //i=8
printf("%d,%d,%d,%d",i,i,temp1,temp0);
所以打印结果是8,8,7,8
另外在TC2.0下面打印结果是:8,7,7,8
而你说你在vc6下面是:8,7,8,8
看来这确实是和编译器有关,三个编译器居然出来的是三个不同结果。而这种代码在实际编程是是不可能写出这么歧义的代码的。。。。。
[[it] 本帖最后由 hoodlum1980 于 2008-2-25 04:52 编辑 [/it]]