C/C++语言难点---指针

前言
今晚又将以前学习的东西总结了下,在学习过程中,很多小伙伴对于指针操作存在疑惑,尤其在数据结构中,指针可以说为链表和树的核心,还有在内存操作上有了指针也是如鱼得水,那么接下来让我们走进指针的大门吧!
一、内存四区模型
[在这里插入图片描述](https://img-blog.csdnimg.cn/20190902211414924.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzODgzNjg0,size_16,color_FFFFFF,t_70

静态区:全局变量/静态变量/常量
代码区:常量字符,指令
栈区:局部变量,部分指针变量
堆区:malloc/free new/delete

在这里插入图片描述二、指针
1.初始化方式:

一级指针与二级指针两种不同的初始化方式
int a=1; <<>>> int a=1; <<>>> int b=1 <<>>> int b=1;
int *pa; <<>>> int *p=&a <<>>> int **pb; <<>>> int **pb=&b;
pa = &a; <<<<<<<< >>>>>>>>> pb=&b;

(1)代码结果显示:

int main()
{
int a=1,b=2;
int *pa;
char *pb;
printf("&a:%x\n", &a);//a的地址
printf("&b:%x\n", &b);//b的地址
printf("&pa:%x\n", &pa);//野指针随机分配内存pa地址
printf("&pb:%x\n", &pb);//野指针随机分配内存pb地址
printf("\n");
pa = &a;
printf(“pa:%x\n”, pa);//a的地址
printf("&pa:%x\n", &pa);//pa的地址
printf("\n");
int **ptr=&pa ; //等同于int **ptr; ptr=&pa;
printf("**ptr:%x\n", **ptr);//等于pa地址所指向的值
printf("*ptr:%x\n", *ptr);//等于地址a
printf(" ptr:%x\n", ptr);//等于地址pa
printf(" &ptr:%x\n", &ptr);//ptr地址值
printf("\n");
*ptr = &b; // 赋值;
printf("**ptr:%x\n", **ptr);//等于b值
printf("*ptr:%x\n", *ptr);//等于地址b
printf(“ptr:%x\n”, ptr);//等于地址pa
printf("&ptr:%x\n", &ptr);//ptr地址值
return 0;
}
在这里插入图片描述
(2)结果显示:

&a:3ef844
&b:3ef838
&pa:3ef82c
&pb:3ef820
pa:3ef844
&pa:3ef82c
**ptr:1
*ptr:3ef844
ptr:3ef82c
&ptr:3ef814
**ptr:2
*ptr:3ef838
ptr:3ef82c
&ptr:3ef814

注:*p放在等号左边相当于写内存,*p放在等号右边赋值读内存

int a=1,c=4;
printf(“old&a:%x\n”, &a);
printf(“old&c:%x\n”, &c);
int *p =&a;
c=*p;
printf(“new&c:%x\n”, &c);
printf(“new&a:%x\n”, &a);
printf(“c:%x\n”, c);
printf("*p:%x\n", *p);
printf("&p:%x\n", &p);
printf("\n");

结果

old&a:3bfb3c
old&c:3bfb30
new&c:3bfb30
new&a:3bfb3c
c:1
*p:1
&p:3bfb24

2…指针数组,数组指针

(1)指针数组
指针数组首先是一个数组,数组占多少字节由数组本身决定,int *p[3],该指针32位系统下是3×4=12个字节,第一部分是类型,第二部分是星号,第三部分是变量名,第四部分数数组的大小, [ ] 优先级要高于 * ,所以我们的变量名 p 是先和 [ ] 结合形成数组,所以他就是一个数组,然后在和 int * 结合 ,这就是我们的指针数组。相当于p[0] p[1] p[2] 三个指针,
(2)数组指针
使用指针指向一个数组,在32位系统下永远是占4个字节,至于它所指向的数组占多少字节是不知道的,int (*p)[5],相当于 p[ ][5]的二维数组
(3)一维两种和二维数组三种表示方法

值 a[i] =(a+i))
地址:a+i=&a[i]
值: a[i][j]]=
(a[i]+j)= ((a+i)+j)
地址:&a[i][j]=a[i]+j=*(a+i)+j

(4) 代码显示

//一维数组指针应用
int a[4] = { 1,2,3,4 };
int *p = a;
for (int i = 0; i < 4; i++)
{
printf("%d\n", p[i]);
printf("%x\n", &p[i]);
}
printf("\n");
for (int i = 0; i < 4; i++)
{
printf("%d\n", *(p + i));
printf("%x\n", (p+i));
}
printf("\n");

//二维数组指针应用
int b[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12 };
int (*c)[4];
c= b;//指向首地址&b[0][0];
printf("%d\n", c[0][2]);//第一行第三列
printf("%d\n", c[1][2]);//第二行第三列
printf("%d\n", ((c+1)+2));//第二行第三列
printf("\n");

//二维指针数组应用
int f[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
int *p1[3];
p1[0] = f[0];//指向第一行首地址
p1[1] = f[1];//指向第二行首地址
p1[2] = f[2];//指向第三行首地址
printf("%d\n", *p1[0]+1);//第一行第二列
printf("%d\n", *p1[1]+1);//第二行第二列
printf("%d\n", *p1[2]+2);//第三行第三列

结果
1
3df958
2
3df95c
3
3df960
4
3df964
1
3df958
2
3df95c
3
3df960
4
3df964
7
7
3df8a0
3df8a4

3.函数指针与指针函数
在程序中定义一个函数,编译时会为该函数分配一段存储空间,这段存储空间首地址即为函数地址。可以通过修改该指针变量来更改函数名,可以参考学习C++中结构体中定义回调函数内容来学习该部分内容。

(1)定义方式:函数返回值类型 (* 指针变量名) (函数参数列表)
int add(int x); /声明一个函数/
int (*p1) (int x); /定义一个函数指针/
p =add; /将add函数的首地址赋给指针变量p1/

#include<stdlib.h>
#include<stdio.h>
#include
#include
using namespace std;
int max(int x, int y)
{
return x > y ? x : y;
}
int main()
{
int(*p)(int, int) = &max; // &可以省略
int a=1, b=2, c=3, e;
//等价,e = max(max(a, b), c)
e = p(p(a, b), c);
printf(“最大的数字是: %d\n”, d);
system(“pause”);
return 0;
}

(2)函数调用打个比方:你是老板,你可以让你你秘书干一些日常事务,秘书返回事务完成的信息。

在这里插入图片描述

#include<stdlib.h>
#include<stdio.h>
#include
#include
using namespace std;
void CallPrintf()
{
printf(“我是秘书,我来汇报任务情况\n”);加粗样式
}
//实现函数回调
int main(int argc, char* argv[])
{
CallPrintf();
system(“pause”);
return 0;
}

(2)回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。打个比方:你是老板,除了你可以让你你秘书干一些秘书自己的日常事务外,你将产品经理的电话直接给了你的秘书,当你要向产品经理分配任务时,秘书首先打电话给经理,等经理完成任务后才向老板汇报完成情况。
在这里插入图片描述

#include<stdlib.h>
#include<stdio.h>
#include
#include
using namespace std;
void chanpinjingli()
{
printf(“我是产品经理,我的调研已完成\n”);
}
//定义实现回调函数的"调用函数"
void CallPrintf(void(chanpinjing_phone_number)())
{
chanpinjing_phone_number();
printf(“我是秘书,我来汇报任务情况\n”);
}
//实现函数回调
int main(int argc, char
argv[])
{
CallPrintf(chanpinjingli);
system(“pause”);
return 0;
}

结果:

我是产品经理,我的调研已完
我是秘书,我来汇报任务情况

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页