C语言指针的*++p,++*p,*p++,(*p)++,*(p++),++(*p),*(++p)代码画图理解。

C语言指针的操作确实让我琢磨不透,调试了一下午之后,好像明白是怎么回事了,写个博文记录一下吧,怕忘记了。

一、前置++与后置++

首先,我们来研究一下前置++ 和后置++的区别。

  • ++在前,先增再用
void main()
{
	int a = 1;
	int b = ++a+1;//++运算符优先于+号,所以先计算++a,++在前,先增再用,a自增为2,再与后面的1进行运算 b=2+1=3
	printf("b=%d,a=%d", b, a);
}
  • 运行结果
    在这里插入图片描述

  • ++在后,先用后增

  • 代码示例:

#include<stdio.h>
void main()
{
	int a = 1;
	int b = 1+a++; //++运算符优先于+号,所以先算a++,又因为++在后面,所以先把a用掉,就是先计算1+a,a=1所以1+a=2,然后a再自增。a也变成了2。
	printf("b=%d,a=%d",b,a);
}
  • 运行结果

在这里插入图片描述
前置- -和后置- -与加一样,–在前面,先自减,再计算,–在后面先计算在自减。

  • 前置- - 先自减再用
void main()
{
	int a = 1;
	int b = --a + 1;//--在前,先自减,再运算,a自减为0,再计算 b=0+1=1
	printf("b=%d,a=%d", b, a);
	}
  • 运行结果
    在这里插入图片描述

  • 后置- - 先用再自减

 void main()
{
	int a = 1;
	int b = 1 + a--;//--运算符优先于-号,所以先算a--,又因为--在后面,所以先把a用掉,就是先计算1+a,a=1所以1+a=2,然后a再自减,a变成了0。
	printf("b=%d,a=%d", b, a);
}

运行结果
在这里插入图片描述

二、*p和p,指针指向的内存空间,和指针地址

p就是一个指针,保存的是地址,*p是操作指针所指向的内存空间。
指针指向谁,就把谁的地址赋值给指针
假如我有一个变量a=100; 然后定义一个指针,让他指向变量a的内存空间。
如图:

在这里插入图片描述

#include<stdio.h>
void main()
{
	int a = 100; //定义变量a
	int* p;//定义指针p
	p = &a;//指针指向a(就是把a)的地址给指针,所以a要取地址。
	printf("p=%p,&a=%p", &a, p);//可以看出来指针的地址和变量的地址是一样的

可以看到他们俩的结果是一样的。p和a是同一块内存空间
在这里插入图片描述
假如下面我操作*p,就是在改变变量a的值。

#include<stdio.h>
void main()
{
	int a = 100; //定义变量a
	int* p;//定义指针p
	p = &a;//指针指向a(就是把a)的地址给指针,所以a要取地址。
	printf("p=%p,&a=%p", &a, p);//可以看出来指针的地址和变量的地址是一样的
	*p = 10;//*p操作指针所指向的内存空间,也就是a的值。通过指针把a的值改成了10
	printf("这是通过*p操作之后的a=%d\n",a);

在这里插入图片描述
讨论完了指针,我们来讨论

三、开始讨论 *++p,++*p,*p++,(*p)++,*(p++)

*和++属于同一级运算符,结合方向是从右至左

(一)、*++p 按照从右到左的结合顺序,我们是不是应该先算++p(p和++结合是地址自增),然后再取*,取*就是取指针所指向的内存空间。

  • 代码示例:
	int arr[3] = { 1,4,6 };//定义了一个数组,3个元素
	int* p = arr;//将指针指向素组首元素地址,数组名就是首元素地址,所以不用取地址了
	printf("执行前的地址为:%p\n", p); //执行语句以前打印一哈p的地址
	int a = *++p;//执行语句
	printf("执行后的地址为%p\n", p);//这是执行语句以后的地址
	printf("*++p=%d\n", a)//打印*++p的结果

在这里插入图片描述

代码分析:可以看到,执行后的地址比执行前的地址多了4,因为一个int类型的占是4个字节,所以执行后的地址为00f8fe48, 地址先增加了4个,所以指针的指向就跳到了素组的第二个元素,然后再取*,所以就打出了p++=4,所以可以看到先执行了p++让地址增加1个(增加一个是占用的是4个字节的空间),然后再运算打印指针所指向的内存空间。

  • 画图分析
    在这里插入图片描述

(二)、++*p 按照从右到左的结合顺序,我们是不是应该先算*p,再计算++。

  • 代码示例
	int arr[3] = { 1,4,6 };
	int* p = arr;//将指针指向素组首元素地址,数组名就是首元素地址,所以不用取地址了
	printf("执行前的地址为:%p\n", p);
	int a = ++ *p;
	printf("执行前的地址为:%p\n", p);
	printf("数组的第一个元素:%d\n", arr[0]);//这一步是验证指针改变了数组元素的值。执行 ++ * p后,数组的首元素的值也发了变化。
	printf("++*p=%d\n", a);

在这里插入图片描述

本例中,先*p取值是1,++在前,所以先计算++ , *p的计算结果是1,再++的结果就变成了2,然后再用a打印出来。通过指针操作了素组的首元素的值也变成了2。地址没有发生变化。

  • 画图理解
    在这里插入图片描述
    (三)、*p++ 按照从右到左的结合顺序,先算p++,又因为++在后,所以先把p用掉和*进行结合运算后再增,用掉以后p的地址还是原来的地址(此时还没有进行自加)当计算完*p之后,p的地址+1。
    代码示例:
	int arr[3] = { 1,4,6 };
	int* p = arr;
	printf("执行前的地址为:%p\n", p);
	int a = *p++;
	printf("执行前的地址为:%p\n", p);
	printf("*p++=%d\n", a);

在这里插入图片描述

代码分析:本例中,从右到左,先计算p++,++在后,先用在增,p先和*结合,计算*p,p存的是数组的首元素地址,所以*p的值是1,所以打印的结果*p++是1,计算完*p之后,p再++,就是地址自加,指向就变成了数组的第二个元素。由原来的0093f910增加到009f914。

  • 画图分析:
    在这里插入图片描述
    (四)、(*p)++ :有括号先算括号里面的,在进行++。
	int arr[3] = { 1,4,6 };
	int* p = arr;
	printf("执行前的地址为:%p\n", p);
	int a = (* p)++;
	printf("执行前的地址为:%p\n", p);
	printf("(* p)++=%d\n", a);

在这里插入图片描述

代码分析:本例中,有括号先算括号里的,p指向的是arr[0]的地址,所以*p=1,++在后,所以先用在自增,先用就是先赋值给a,在++,所以打印出来的结果是1而不是2。

五、*(p++):有括号先算括号,所以先执行p++,又因为++在后,所以先用再自加,(和*p++是一样的顺序)p先和*进行结合,然后地址再++。
代码:

	int arr[3] = { 1,4,6 };
	int* p = arr;
	printf("执行前的地址为:%p\n", p);
	int a = *(p++);
	printf("执行前的地址为:%p\n", p);
	printf("*(p++)=%d\n", a);

在这里插入图片描述

代码分析和*p++基本是一样的(有括号先括号)

六、++(*p):有括号先括号,先计算*p,然后++在前,先增再用。
代码:

	int arr[3] = { 1,4,6 };
	int* p = arr;
	printf("执行前的地址为:%p\n", p);
	int a = ++(*p);
	printf("执行前的地址为:%p\n", p);
	printf("++(*p)=%d\n", a);

在这里插入图片描述

分析:本例中,有括号先括号,先计算*p,*p是1,然后++在前,先增再用。所以++(*p)的结果是2

(七)*(++p) 有括号先括号,先算++p,++在前,所以先++,地址自增后再进行*运算。和*++p是一样的顺序。
代码:

	int arr[3] = { 1,4,6 };
	int* p = arr;
	printf("执行前的地址为:%p\n", p);
	int a = *(++p);
	printf("执行前的地址为:%p\n", p);
	printf("*(++p)=%d\n", a);

在这里插入图片描述

分析:本例中,*(++p)先算括号里面的++p ,++在前,所以地址先做自增,再取*,所以打印的是数组的第二个元素,a[1]也就是4。


以上就是对于这几个代码的分析

C语言学习真的是不能靠看懂,要亲自动手调试,画图才能更好的理解。

  • 9
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值