1.指针数组
什么是指针数组呢?
比如:
int *arr[10]; int *a[4]; int **arr[10];
以上这些都是指针数组,为什么 呢?首先 拿第一个为例,arr先与[10]结合成为一个数组,然后这个数组里存着10个元素,每个元素的类型为int*;第二个也一样。第三个的意思是arr与[10]结合成为一个数组,数组的元素类型为int**。总的来说就是存放指针的数组叫指针数组。它怎么用呢?如下:
int *arr[10] = {"hello","werer"};
这里面因为存放的都是一个int型的指针,所以每个指针都可以指向一个字符串。
2.数组指针
那么数组指针又是什么呢?
比如:
int (*p)[10];
这种类型的叫做数组指针,首先*与p结合,形成一个指针,然后指向一个有10元素的数组。概括来说就是p是一个指向数组的指针,所以叫做数组指针。那它有什么作用呢?如下:
int arr[] = {1,23,4,5}; int (*p)arr = &arr; void A(int (*p)[5]) { } int main() { int a[3][5]; A(a); return 0 }
首先如我们看到的一样,他可以存放一个数组的地址,其次第二个就是它可以接受一个二维数组的传参。因为二维数组的数组名是第一行的地址,所以数组指针就是用一个指针来指向第一行,再用数组指针的下标来找到一行的每个元素,指针加一就可以指向下一行。
警告:
int arr[5]; int *pa[10]; int (*ppa)[10];
如果出现下面的情况你认为可以吗?
int (*ppa)[10] = &pa; int (*ppa)[10] = &arr;
这样是不可以的,第一行数组内的每个元素是int型,而pa内的每个元素是int*,所以不可以这样做。
第二行的arr数组虽然每个元素是int型,但是这个数组内只有5个元素,而ppa这个数组指针指向的是一个有10个类型的数组,所以类型不匹配,也不可以。
3.存放数组指针的数组
首先它是数组,里面存放的都是数组指针,那么在数组指针的基础上就可以写成这样
int (*pppa[4])[10];
这就是一个数组指针的数组。
4.函数指针
其实函数也有地址,函数名就是它的首地址,这就和一维数组的数组名一样。让我们先看一段代码。
#include<stdio.h> #include<stdlib.h> void Asd() { printf("hehe"); } int main() { printf("%p\n", Asd); printf("%p\n",&Asd); system("pause"); return 0; }
这样就可以看出,函数名就是函数的首地址了吧。函数名和取地址函数名是一样的,这点与数组不相同。
void (*p)() = Asd;
上面这个就是一个给函数指针赋值的过程,*p要加括号,不然p就会先与()结合之后再与*结合,这样p就不是一个指针了。
()里放的是实参的类型,因为这个函数没有传参所以不放任何东西。
5.函数指针数组
数组是存放相同类型的存储空间,如果将函数指针放入数组里就是函数指针数组,既然是数组就要先与[]结合,所以数组指针如下
void (*p[3])();
这里面可以存放三个函数指针,这就是函数指针数组。
用下面一段代码来熟悉一下函数指针数组:
#include<stdio.h> #include<stdlib.h> void menu() { printf("**********************\n"); printf("***1.Add 2.Sub ****\n"); printf("***3.Mul 4.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 Mul(int x, int y) { return x*y; } int Div(int x, int y) { return x/y; } int main() { int i = 0; int j = 0; int input = 0; int ret = 0; int (*put[5])(int, int) = {0, Add, Sub, Mul, Div}; do { menu(); printf("请选择:"); scanf("%d", &input); if(input>=1&&input<=4) { printf("请输入两个参数:"); scanf("%d%d", &i, &j); ret = (*put[input])(i, j); printf("ret = %d\n", ret); } else if(input<0||input>4) { printf("输入错误\n"); } else { printf("退出游戏\n"); } }while(input); system("pause"); return 0; }
这是一个实现计算器功能的函数,其中因为加减乘除函数的类型相同,所以可以将它们四个数组的地址用函数指针数组来存放。这里面的(*put[5])(int , int )就是一个函数指针数组。这样你对函数指针是数组有了一定的了解了吧。
6.函数指针数组的指针
既然了解了上面的函数指针数组,我们就再深入了解函数指针数组的指针。听起来有点绕口,但是我们慢慢分析就可以了,
首先他是一个指针,所以他必须与*先结合,他指向的是一个存放函数指针的数组,所以就可以写成这样:
void (*(*p)[3])();
也就是在函数指针数组的基础上将p在变成一个指针。它有什么作用呢?
它可以存放函数指针数组的地址。让我们在用一段代码了解一下:
#include<stdio.h> #include<stdlib.h> void Asd() { printf("hehe"); } int main() { void (*p)() = Asd;//用一个函数指针来指向这个函数 void (*q[3])() ;//函数指针数组 q[0] = p;//用一个函数指针数组来存放这个函数指针 void (*(*a)[3])() = &q;//用一个函数指针数组的指针指向这个函数指针数组 system("pause"); return 0; }