【C】由printf("%d\t%d\t%d\n",a,a+=(a++),a);引起的思考
2016-03-16 23:54
399 查看
#include<stdio.h> int main() { int a=1,a1=1; int b=1,b1=1; printf("(1)后自加:\n"); printf("a+=(a++):\n");// printf("%d\t%d\t%d\n",a,a+=(a++),a); printf("%d\n",a); printf("a1+(a1++):\n");// printf("%d\t%d\t%d\n",a1,a1+(a1++),a1); printf("%d\n",a1); printf("\n(2)前自加:\n"); printf("b+=(++b):\n");// printf("%d\t%d\t%d\n",b,b+=(++b),b); printf("%d\n",b); printf("b1+(++b1):\n");// printf("%d\t%d\t%d\n",b1,b1+(++b1),b1); printf("%d\n",b1); return 0; }
总的来说挺纠结的,实际上面的结果计算涉及到如下几点:
(1) 当printf()参数表中有自加表达式时执行顺序:
后自加:以 8: printf("%d\t%d\t%d\n",a,a+=(a++),a);在VC6.0中的反汇编结果(见文末)为例:
1)倒数第一个参数入栈 (这里值得注意的是入栈时数据占的字节数依据是参数表中该变量的数据类型,且float类型按照double类型的字节数)
2)倒数第二个参数入栈:取(a++)的值得① --> 计算①+a得② --> 把②赋值给a
3)倒数第三个参数入栈
4)控制字符串入栈
5)输出 (这里值得注意的是输出时从栈中取数据时按照格式说明符对应的字节数,且%f对应double类型的字节数)
6)变量a自加1,并更新
前自加:以16: printf("%d\t%d\t%d\n",b,b+=(++b),b);在VC6.0中的反汇编结果(见文末)为例:
1)倒数第一个参数入栈
2)倒数第二个参数入栈:变量b自加1,并更新-->取b的值得① --> 计算b+①得② --> 把②赋值给b
3)倒数第三个参数入栈
4)控制字符串入栈
5)输出
(2)加法运算符'+'的计算顺序
这个也不用怀疑,计算顺序一定是先计算左操作数对应的表达式。
另外,要区分“计算”和“取值”的区别,如果左操作数只是一个变量,而右操作数是表达式。则先计算右操作数表达式的值,然后从左操作数的变量中取值再与该表达式相加。
因此: a+(++a)是 (变量a自加后数值+变量a自加后数值)而不是 (变量当前数值+变量a自加后数值)
以下是部分语句在VC6.0中反汇编结果:
8: printf("%d\t%d\t%d\n",a,a+=(a++),a); 0040D75E mov eax,dword ptr [ebp-4] 0040D761 push eax 0040D762 mov ecx,dword ptr [ebp-4] 0040D765 add ecx,dword ptr [ebp-4] 0040D768 mov dword ptr [ebp-4],ecx 0040D76B mov edx,dword ptr [ebp-4] 0040D76E mov dword ptr [ebp-14h],edx 0040D771 mov eax,dword ptr [ebp-14h] 0040D774 push eax 0040D775 mov ecx,dword ptr [ebp-4] 0040D778 push ecx 0040D779 push offset string "%d\t%d\t%d\n" (00422fdc) 0040D77E mov edx,dword ptr [ebp-4] 0040D781 add edx,1 0040D784 mov dword ptr [ebp-4],edx 0040D787 call printf (00401080) 0040D78C add esp,10h 9: printf("%d\n",a); 0040D78F mov eax,dword ptr [ebp-4] 0040D792 push eax 0040D793 push offset string "%c\n" (0042201c) 0040D798 call printf (00401080) 0040D79D add esp,8 10: printf("a1+(a1++):\n");// 0040D7A0 push offset string "a1+(a1++):\n" (00422fd0) 0040D7A5 call printf (00401080) 0040D7AA add esp,4 11: printf("%d\t%d\t%d\n",a1,a1+(a1++),a1); 0040D7AD mov ecx,dword ptr [ebp-8] 0040D7B0 push ecx 0040D7B1 mov edx,dword ptr [ebp-8] 0040D7B4 add edx,dword ptr [ebp-8] 0040D7B7 mov dword ptr [ebp-18h],edx 0040D7BA mov eax,dword ptr [ebp-18h] 0040D7BD push eax 0040D7BE mov ecx,dword ptr [ebp-8] 0040D7C1 push ecx 0040D7C2 push offset string "%d\t%d\t%d\n" (00422fdc) 0040D7C7 mov edx,dword ptr [ebp-8] 0040D7CA add edx,1 0040D7CD mov dword ptr [ebp-8],edx 0040D7D0 call printf (00401080) 0040D7D5 add esp,10h 12: printf("%d\n",a1); 0040D7D8 mov eax,dword ptr [ebp-8] 0040D7DB push eax 0040D7DC push offset string "%c\n" (0042201c) 0040D7E1 call printf (00401080) 0040D7E6 add esp,8 13: 14: printf("\n(2)前自加:\n"); 0040D7E9 push offset string "%d\t%d\n" (00422fc0) 0040D7EE call printf (00401080) 0040D7F3 add esp,4 15: printf("b+=(++b):\n");// 0040D7F6 push offset string "b+=(++b):\n" (00422fa8) 0040D7FB call printf (00401080) 0040D800 add esp,4 16: printf("%d\t%d\t%d\n",b,b+=(++b),b); 0040D803 mov ecx,dword ptr [ebp-0Ch] 0040D806 push ecx 0040D807 mov edx,dword ptr [ebp-0Ch] 0040D80A add edx,1 0040D80D mov dword ptr [ebp-0Ch],edx 0040D810 mov eax,dword ptr [ebp-0Ch] 0040D813 add eax,dword ptr [ebp-0Ch] 0040D816 mov dword ptr [ebp-0Ch],eax 0040D819 mov ecx,dword ptr [ebp-0Ch] 0040D81C push ecx 0040D81D mov edx,dword ptr [ebp-0Ch] 0040D820 push edx 0040D821 push offset string "%d\t%d\t%d\n" (00422fdc) 0040D826 call printf (00401080) 0040D82B add esp,10h 17: printf("%d\n",b); 0040D82E mov eax,dword ptr [ebp-0Ch] 0040D831 push eax 0040D832 push offset string "%c\n" (0042201c) 0040D837 call printf (00401080) 0040D83C add esp,8 18: printf("b1+(++b1):\n");// 0040D83F push offset string "b1+(++b1):\n" (00422fb4) 0040D844 call printf (00401080) 0040D849 add esp,4 19: printf("%d\t%d\t%d\n",b1,b1+(++b1),b1); 0040D84C mov ecx,dword ptr [ebp-10h] 0040D84F push ecx 0040D850 mov edx,dword ptr [ebp-10h] 0040D853 add edx,1 0040D856 mov dword ptr [ebp-10h],edx 0040D859 mov eax,dword ptr [ebp-10h] 0040D85C add eax,dword ptr [ebp-10h] 0040D85F push eax 0040D860 mov ecx,dword ptr [ebp-10h] 0040D863 push ecx 0040D864 push offset string "%d\t%d\t%d\n" (00422fdc) 0040D869 call printf (00401080) 0040D86E add esp,10h 20: printf("%d\n",b1); 0040D871 mov edx,dword ptr [ebp-10h] 0040D874 push edx 0040D875 push offset string "%c\n" (0042201c) 0040D87A call printf (00401080) 0040D87F add esp,8 21: return 0; 0040D882 xor eax,eax 22: }
相关文章推荐
- xdotool源代码,需要的伙伴请自取
- 变态跳台阶
- 51NOD1515 明辨是非
- 不在编辑状态下的UITableView多选
- 多个Fragment之间的切换
- Ubuntu下的Android Studio某些开发问题
- 跳台阶
- 《FPGA NiosII篇》Part 1工程创建与注意点
- exit() 时或之后还能继续执行php代码的几种办法
- 重建二叉树
- js函数节流-性能-resize
- mysql外键,索引等基本操作 和 跨表复制数据操作
- mysql外键,索引等基本操作 和 跨表复制数据操作
- Library cache内部机制详解
- Linux-2.6.24移植到FL2440开发板
- 二维数组中的查找
- 气体传感器的引脚说明
- Library cache内部机制详解
- [置顶] Android开发错误汇总
- Redis学习(一)-基础理论、字符串命令、列表结构