今天看到一个C语言的面试题:
1 #include<stdio.h> 2 3 #define PRODUCT(X) (X*X) 4 5 int main() 6 { 7 int i = 3, 8 j, k; 9 j = PRODUCT(i++); 10 k = PRODUCT(++i); 11 12 printf("j = %d, k = %d", j, k); 13 }
先说答案吧:
j = 9, k = 49
我本来觉得自己C学的还不错的, 可是上来一算,j = 3 * 4 = 12, k = 6 * 7 = 42. 跟答案差的太远了, 我又算了几下, 百思不得其解, 看来得从汇编查找原因了.先把宏展开来看:
j = i++*i++;
k = ++i*++i;
先看 j = i++*i++; 的汇编代码:
1 ;语句 j = i++*i++ 的汇编代码 2 ; 3 001013F5 mov eax,dword ptr [i] ;将i值存入eax,eax=3 4 001013F8 imul eax,dword ptr [i] ;做乘法运算,结果9存入eax 5 001013FC mov dword ptr [j],eax ;eax赋值给j,j=9 6 ;上面语句已完成j的赋值运算,下面是对i自加运算的处理 7 001013FF mov ecx,dword ptr [i] ;i的值存入ecx,ecx=3 8 00101402 add ecx,1 ;加法运算,3+1=4,存入ecx 9 00101405 mov dword ptr [i],ecx ;ecx赋值给i,i=4 10 00101408 mov edx,dword ptr [i] ;edx=4 11 0010140B add edx,1 ;edx=4+1=5 12 0010140E mov dword ptr [i],edx ;i=5
哦, 到现在算是整明白了,处理i++时,是先处理其它运算,当其它运算完整以后,再去处理i的自加, 按照这个逻辑, 求k时,先进行++i运算,两次++i以后,i的值变成7, 然后k=7*7=49.这就和答案一样了,原来是这样,看下求k时的汇编语句吧:
1 ; k = ++i*++i; 2 ; 3 ;先是自增运算 4 00101411 mov eax,dword ptr [i] 5 00101414 add eax,1 6 00101417 mov dword ptr [i],eax 7 0010141A mov ecx,dword ptr [i] 8 0010141D add ecx,1 9 00101420 mov dword ptr [i],ecx 10 ;然后求乘 11 00101423 mov edx,dword ptr [i] 12 00101426 imul edx,dword ptr [i] 13 0010142A mov dword ptr [k],edx
看了汇编代码, 和想像中的一样, 呵呵, 看来问题得到解决了, 再给自己加个问题, 如果把j和k全换成i, 结果又怎么样呢?
1 // test.c 2 3 #include<stdio.h> 4 5 int main() 6 { 7 int i = 3; 8 i = i++*i++; 9 printf("%d\n", i); 10 i = ++i*++i; 11 printf("%d\n", i); 12 getchar(); 13 }
当然, 最终的结果是:
11
169
不难理解, i先进行乘法运算, 得到结果9. 再进行两次自增运算, 得到结果11.
后一句运算, i先进行两次自增运算, 得到i=13; 再进行乘法运算, 13 * 13 = 169, 正解.
问题解决.