个人对指针的一些理解

指针是什么?指针是可以指向一个变量地址的值,指针可以通过一个变量的地址来修改该变量的值,这一点可以应用在单机游戏修改数值上(通过特定工具找到某个数值的地址,然后用指针进行修改)。
但是多级指针的含义和各种情况有时候会晕,为了怕忘记,我记录下来我的理解。

#include<stdio.h>
int main()
{
 int a = 10;
 int *p = &a;
 int **pp = &p;
 int ***ppp=&pp;
 printf("地址:&a=%d  &p=%d  &pp=%d\n",&a,&p,&pp);
 printf("各个指针指向的地址:p=%d  pp=%d  ppp=%d\n",p,pp,ppp);
 printf("相关联的地方:p=%d  *pp=%d  **ppp=%d\n",p,*pp,**ppp);
 printf("各个指针所指向的地址的值:*p=%d  **pp=%d  ***ppp=%d\n",*p,**pp,***ppp);
// printf("pp=%d  *ppp=%d\n",pp,*ppp); 
} 

在这里插入图片描述p表示的是a的地址
*p表示的是指针所指向的地址的值(也就是a的值)

pp表示的是指针p的地址
*pp表示的是指针p所指向的地址(也就是a的地址)
**pp表示的是指针p所指向的地址的值(也就是a的值)

ppp表示的是指针pp的地址
*ppp表示的是指针pp所指向的p的地址
**ppp表示的是两级指针pp所指向的一级指针p所指向的地址
***ppp表示的两级指针pp所指向的一级指针p所指向的地址的值(也就是a的值)

多级指针的内容就如此类推(还有疑惑的话,可以运行我注释的那行代码看看)

另外我们可以这样理解,**pp等价于*p,pp等价于p,也就是说我们想对p赋值可以直接对pp进行操作。(结合图片好好理解这里,这是要点)

然后我们再来看一个问题,关于用malloc函数向堆区申请空间的情况。

//代码1:
#include <stdio.h>
#include <stdlib.h>
void ave(int *pp)
{
 printf("pp=%d *pp=%d\n", pp, *pp);
 pp = (int *)malloc(sizeof(int)* 10);
 printf("malloc之后的pp=%d *pp=%d\n", pp, *pp);
}
int main()
{
 int a = 5;
 int *p = &a;
 printf("&a=%d p=%d  &p=%d\n", &a, p, &p);
 ave(p);
 printf("ave之后的&a=%d  a=%d  p=%d  &p=%d\n",&a, a, p, &p);
 p[0] = 1;
 p[1] = 2;
 printf("%d %d\n", p[0], p[1]);
 free(p);
}
//代码2
#include <stdio.h>
#include <stdlib.h>
void ave(int **pp)
{
 printf("pp=%d *pp=%d\n", pp, *pp);
 *pp = (int *)malloc(sizeof(int)* 10);
 printf("malloc之后的pp=%d *pp=%d\n", pp, *pp);
}
int main()
{
 int a = 5;
 int *p = &a;
 printf("&a=%d p=%d  &p=%d\n", &a, p, &p);
 ave(&p);
 printf("ave之后的&a=%d  a=%d  p=%d  &p=%d\n",&a, a, p, &p);
 p[0] = 1;
 p[1] = 2;
 printf("%d %d\n", p[0], p[1]);
 free(p);
}

大家在运行这两个代码之前先想一下,有没有问题,问题在哪里?
运行代码1会发现,程序出现问题了,为什么呢?
我们首先我们看代码1,我们传进去的函数的是p,也就是说是a的地址,这相当于是传进去值。这时候函数中的pp并非主函数中的p而是一个与主函数中的p指向同一个地址a的指针而已,而你malloc分配内存的地址给函数中的pp,毫无作用,因为不会影响到主函数中的p。(概括的说就是传进去的是值,无法影响到主函数中的p)

我们看一下代码1的程序运行图:

在这里插入图片描述

而代码2却可以,这是为什么呢?
因为我们这次传进去的是p的地址,指针p的地址,而不是p的值了。这次我们知道了指针p的地址,那么我们就可以用二级指针pp来操作一级指针p了,通过pp来表示p,从而用malloc分配内存给主函数的中的p了(因为pp等价于p,上面我提到的要点)。这时候程序就不会出现崩溃现象。

我们看一下代码2的程序运行图:
在这里插入图片描述

这个问题还是比较经典的,对理解指针的我有较深的感触。另外代码中用变量a的地址来初始化指针p是为了输出内容,让我好理解指针的含义,一般来说都是用NULL初始化的。如果还是不太懂代码1和2的区别的,可以看一下输出的内容。

函数指针:
int *p(int,int *)//表示一个名为p的函数,其返回值是int *
int (*p)(int,int )//定义一个指向参数为int和int,返回值是int的函数指针。
int *(p)(int,int )//定义一个指向参数为int和int,返回值是int的指向函数的指针(函数指针)。
emmm可以这样说有()的话就表示是一个函数指针,而没()的话就是一个函数了。这样理解是不是很简单了呢?(我不知道我函数指针这样总结对不对啊,求大佬指教)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值