目录
1.指针数组和数组指针
1.指针数组
int* arr1[10]; //整形指针的数组
char *arr2[4]; //一级字符指针的数组
char **arr3[5];//二级字符指针的数组
指针数组简单地说就是存放指针的数组
2.数组指针
int *p1[10];
int (*p2)[10];
//p1, p2分别是什么?
答:
int *p1[10]是指针数组
int (*p2)[10]是数组指针
区分数组指针和指针数组的关键:
观察*是与数据类型结合还是与变量名结合
如果*与数据类型结合那么就是指针数组
但是如果*与变量名结合那么就是数组指针
2.数组传参和指针传参
1.数组传参
那么先看用例:
例1:void test(int arr[]){}
例2:void test(int *arr){}
例3:void test2(int *arr[20]){}
例4:void test2(int **arr){}
int main()
{
int arr[10] = {0};
int *arr2[20] = {0};
test(arr);
test2(arr2);
}
test函数的参数是arr————一个数组名:数组名可以代表数组首元素的地址
那么对于test函数而言,形参部分就可以传一个一级指针或者一个地址
所以例1和例2都是正确的
text2函数的参数是arr2————也是一个数组名:数组名可以代表数组首元素的地址
但是arr2是一个指针数组名,所以text2的参数是一个指针数组的首地址
那么例3的传的参数就是正确的,
例4:实参是指针数组的首地址;那么需要存放它就必须要就需要一个二级指针;
所以例4也是正确的
2.函数传参
先看用例
void test(char **p)
{
}
int main()
{
char c = 'b';
char*pc = &c;
char**ppc = &pc;
char* arr[10];
test(&pc);
test(ppc);
test(arr);//Ok?
return 0;
}
test函数的形参是一个二级指针
对于test(&pc)来说,pc是一个char类型的指针,对pc取地址,那么&pc自然就要用一个二级指针接收喽,所以test(&pc)是正确的,
对于test(ppc)来说,ppc是一个二级指针,所以也是正确的
对于test(arr)来说,arr是一个指针数组的首地址,需要二级指针来接收,所以test(arr)也是正确的
3.函数指针和函数指针数组
1.函数指针
函数指针:是一个指向函数的指针
函数指针的基本格式;函数返回类型 (*函数名)(形参);
先看代码:
void test(char*,char*){}
int main()
{
void (*p)(char*,char*)=test;
}
观察代码可见
1.如果想要用一个指针来指向一个函数,那么就需要用一个函数指针
2.test是一个函数名居然可以和指针配对,那么我们就可以得出结论,函数的函数名与数组的数组名类似,都可以代表他们的首地址;
使用函数指针的注意事项:
1.函数的返回类型要和指针的返回类型相同
2.指针形参的类型,要和函数形参的类型相同
2.函数指针数组
顾名思义函数指针数组就是一个存放函数指针的数组
函数指针数组的基本格式:函数返回类型 (*函数名[数据个数]) (形参列表)
我们看这个格式,可以看出这个函数指针数组的每个元素的形参列表和函数返回类型都是相同的
所以我们在用函数指针数组存放函数地址的时候,也必须让存放的每个函数的函数返回类型和形参列表都是相同的。
#include<stdio.h>
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a*b;
}
int div(int a, int b)
{
return a / b;
int main()
{
int (*p[4])={add,sub,mul,div};
}
这就是函数指针最简单的写法,p通过下标来访问里面的4个函数加减乘除;