前情提要:
做程序员嘛,大大小小都会加入许多技术学习交流群(虽然群里不一定都是在学习交流),然后有一次群里有个小伙伴就问了这个问题
-
回合一:
截图中的代码是这样的:
#include <stdio.h>
int main()
{
int* p;
int a[]={ 4,3,6,5,1 };
p = a;
int b = *p++;
int c = (*p)++;
printf("%d %d\n",b,c); //4 3
printf("%d %d\n", *p++, (*p)++); //5 4
return 0;
}
当时我只扫了printf的那两行,并且还没有意识到问题的关键,我一看第二行printf明显多做了一次运算,就直接在图片上给他指出来了。
-
回合二
然后,他又问了下面一个问题:
就是把中间的变量b和c的赋值和打印去掉:
#include <stdio.h>
int main()
{
int* p;
int a[]={ 4,3,6,5,1 };
p = a;
//int b = *p++;
//int c = (*p)++;
//printf("%d %d\n",b,c); //4 3
printf("%d %d\n", *p++, (*p)++); //5 4
return 0;
}
看样子完全是按照我给的思路来的,既然多做了一次运算,那就去掉一次运算看看。到这里我开始意识到了不对,为什么!!还是5和4!!!
在脑子短暂的懵了一下之后,我像抓住的救命稻草一样,看到了p后面的++,这个时候我还没有意识到问题的关键在于p是个指针。
-
回合三
但我还没来得及说的时候,他又接着抛出了他的疑问:
这时候,我赶紧说出了我的想法:
然后如你们所见,我自己也晕了,为了验证,我自己运行了一下代码,确实如他所说,两次运行的结果不一样。
所说的两次是指:
第一种情况:
#include <stdio.h>
int main()
{
int* p;
int a[]={ 4,3,6,5,1 };
p = a;
int b = *p++;
int c = (*p)++;
printf("%d %d\n",b,c); //4 3
return 0;
}
第二种情况:
#include <stdio.h>
int main()
{
int* p;
int a[]={ 4,3,6,5,1 };
p = a;
printf("%d %d\n", *p++, (*p)++); //5 4
return 0;
}
场面一度有些尴尬,我俩互相开始圆场
但是,我不服气啊!嘴上说着蹲一个答案,实则自己悄咪咪去找资料了。
-
最后
经过各种查资料,我终于得出以下结论。
先看第一种情况
为什么输出b和c 的值是4、3?
一、
b = *p++;
(1)b = p指向地址的内容,即a[1],内容为4
(2)p指向的地址自增,变成指向a[2] //地址自增
二、
c = (*p)++;
(1) c = p指向的内容,即a[2],内容为3
(2) 因为有"( )",所以是p指向的内容自增(非地址自增),即3+1 =4,a[2]=4 //值自增
综上来说,b=4, c= 3
再看第二种情况
为什么输出是5和4?
这里我也小卡了一下,按照上面的思路,我得到的会是4和3,然而实际上我得到的却是5和4。卡了一会儿,才想到printf()内部的执行顺序是从右向左的,再结合之前的思路就可以得到正确的结果了。
(下班了,所以最后这张截图是手机微信截图)