C学习笔记001——关于*p++和(*p)++的思考(菜鸟篇)

209 阅读3分钟

前情提要:

做程序员嘛,大大小小都会加入许多技术学习交流群(虽然群里不一定都是在学习交流),然后有一次群里有个小伙伴就问了这个问题

  • 回合一:

1681178934632.png

截图中的代码是这样的:

#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明显多做了一次运算,就直接在图片上给他指出来了。

dd6917ed43354c18f97be308a96ca45.png

当时我并没有注意到问题的严重性,甚至都没有注意到p是个指针,单凭扫的那一眼就想当然的以为是他粗心了,没注意到第二行printf多做了次运算。
  • 回合二

然后,他又问了下面一个问题:

1681179779075.png

就是把中间的变量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是个指针。

  • 回合三

但我还没来得及说的时候,他又接着抛出了他的疑问:

image.png

这时候,我赶紧说出了我的想法:

1681182065095.png

然后如你们所见,我自己也晕了,为了验证,我自己运行了一下代码,确实如他所说,两次运行的结果不一样。

所说的两次是指:

第一种情况:

#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;
}

1681182375920.png

第二种情况:

#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;
}

1681182542350.png

场面一度有些尴尬,我俩互相开始圆场

1681182663197.png

但是,我不服气啊!嘴上说着蹲一个答案,实则自己悄咪咪去找资料了。

  • 最后

经过各种查资料,我终于得出以下结论。

先看第一种情况

为什么输出b和c 的值是4、3?

1681183089225.png

一、
b = *p++;
(1)b = p指向地址的内容,即a[1],内容为42)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()内部的执行顺序是从右向左的,再结合之前的思路就可以得到正确的结果了。

28279e77333c4d588086f58258ec3a6.jpg

(下班了,所以最后这张截图是手机微信截图)