本文主要是介绍指针(4)有点难,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
指针(4)
来做个简单的回顾:
指针数组:
1.是数组
2.是存放指针的数组
char* arr1[5];
int*arr2[3];
数组指针:
1 .是指针
2 .指向数组的指针
字符指针:char*pc;
整型指针:int*pi;
int (*p) [10];//P就是数组指针,p指向的数组有10个元素,每个元素的类型是int
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{int arr[10] = { 0 };int(*p)[10] = &arr;//取的是整个数组的地址return 0;
}
例子:
想使用p这个数组访问arr数组的内容
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int(*p)[10] = &arr;//取的是整个数组的地址int i = 0;
for (i = 0; i <= 10; i++)
{printf("%d", p[i]);//*(p+i)
}
1 .二维数组传参的本质
代码如下:
void Print(int arr[3][5], int r, int c)//int (*arr)[5]
{int i = 0;for (i = 0; i <=r; i++){for (int j = 0; j <=c; j++){printf("%d", arr[i][j]);//*(*(arr+i)+j)//*(arr+i)==arr[i]//arr[i]是第i行的数组名,数组名又是数组首元素的地址,arr[i]=&arr[i][0]}printf("\n");}
}int main()
{int arr[3][5] = { (1,2,3,4,5),(2,3,4,5,6),(3,4,5,6,7) };Print(arr, 3, 5);return 0;
}
前情回顾:
一维数组传参
数组名是首元素的地址,一维数组传参的时候,其实传递的是首元素的地址。
函数的参数可以写成数组,也可以写成指针。
那二维数组呢?
其实二维数组的数组名也是数组首元素的地址,二维数组的数组名就是它第一行的地址,第一行是一个一维数组,传过去的是第一行这个一维数组的地址
[外链图片转存中…(img-Lf2wiLHP-1715345940161)]
[外链图片转存中…(img-HzRavJos-1715345940162)]
总结:
arr[i]==*(arr+i)
arr[i] [j]=* (*(arr+i)+j)
不管是一维数组还是二维数组,形参可以写成数组,也可以写成指针,这里要对数组名做深入理解
2 .函数指针变量
void Add(int x, int y)
{return x + y;
}int main()
{int a = 2;int b = 6;Add(a, b);printf("%p\n", &Add);return 0;
}
运行结果:
[外链图片转存中…(img-lowcQ39K-1715345940163)]
小小的不同:
&函数名和函数名的地址没有不同
[外链图片转存中…(img-815uKMMu-1715345940163)]
[外链图片转存中…(img-1Si0XL6D-1715345940163)]
函数指针变量的注意点:
我们之前学习调用函数的时候
形式如下:
int ret2 = Add(4, 5);
其实函数指针变量也可以写成另外一种形式,也是可以的:
int ret3 = pf(4, 5);
但是写上*的时候,不要忘记加(),因为这时候pf会和(4,5)相结合,调用的·是函数值的地址,这就有问题了
函数指针类型解析:
int (*pf3) (int x, int y)
| | ------------
| | |
| | pf3指向函数的参数类型和个数的交代
| 函数指针变量名
pf3指向函数的返回类型
int (*) (int x, int y) //pf3函数指针变量的类型
3 .两段有趣的代码
代码1:
(*(void (*)())0)();
[外链图片转存中…(img-pL9wxN6Q-1715345940163)]
代码2:
void (*signal(int , void(*)(int)))(int);
[外链图片转存中…(img-FNyDCtyc-1715345940164)]
[外链图片转存中…(img-3hjNYgd0-1715345940164)]
可以这样理解,但是语法不允许这样写
4 .typedef关键字
typedef unsigned int unit;
int main()
{unsigned int num;unit num;return 0;
}
对数组指针重命名:
typedef int(*parr_t)[10]//一定要把指针放里面
int main()
{int arr[6] = { 0 };int(*p) = &arr;parr_t p2 = &arr;return 0;
}
对函数指针重命名:
int Add(int x, int y)
{return x + y;
}
typedef int(*pf_t)(int, int);int main()
{int(*pf)(int, int) = Add;pf_t pf2 = Add;return 0;
}
那么我们在有趣的代码这一节中那个函数的声明也可以写成:
typedef void(*pf_t)(int)int main()
{pf_t signal(int,pf_t);return 0;
}
5 .函数指针数组
int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int Plus(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
int main()
{int(*pf[4])(int,int) = {Add,Sub,Plus,Div};//函数指针数组//0, 1 ,2 ,3int i=0;for(i=0;i<4;i++){int ret=pf[i](6,2);printf("%d\n",ret);
}return 0;
}
6 .转移表
函数指针数组的⽤途:转移表
例子:计算器
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void menu(){printf("**************************\n");printf("*******1 .Add 2 .Sub******\n");printf("*******3 .Plus4 .Div******\n");printf("*******0 .exit************\n");printf("**************************\n");}int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int Plus(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
int main()
{int input = 0;int x = 0;int y = 0;int ret = 0;do{menu();printf("请选择:");scanf("%d", &input);int(*prArr[5])(int,int) = {0,Add,Sub,Plus,Div};//函数指针数组if (input >= 1 && input <= 4){printf("请输入两个操作数:");scanf("%d %d", &x, &y);ret = prArr[input](x, y);printf("%d\n", ret);}if (input == 0){printf("您已退出计算器\n");}else{printf("请重新做选择\n");}} while (input);return 0;
}
7 .回调函数是什么?
回调函数就是⼀个通过函数指针调⽤的函数。
如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数 时,被调⽤的函数就是回调函数。回调函数不是由该函数的实现⽅直接调⽤,⽽是在特定的事件或条 件发⽣时由另外的⼀⽅调⽤的,⽤于对该事件或条件进⾏响应。
[外链图片转存中…(img-wA8XZowf-1715345940164)]
ret);
}
if (input == 0)
{
printf(“您已退出计算器\n”);
}
else
{
printf(“请重新做选择\n”);
}
} while (input);
return 0;
}
## 7 .回调函数是什么?回调函数就是⼀个通过函数指针调⽤的函数。如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数 时,被调⽤的函数就是回调函数。回调函数不是由该函数的实现⽅直接调⽤,⽽是在特定的事件或条 件发⽣时由另外的⼀⽅调⽤的,⽤于对该事件或条件进⾏响应。[外链图片转存中...(img-wA8XZowf-1715345940164)]Calc起到了封装的作用
这篇关于指针(4)有点难的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!