指针数组 :
指针数组就是一个整数数组,数组的各个元素都是整数,指向某个内存地址。在c语言以及c++中,数组元素全为指针的数组成为指针数组。一维指针数组的定义形式为:“类型名*数组标识符[数组长度]”。
eg:
int a = 10;
int b = 20
int * arr[5] = {&a,&b};
数组名出现在表达式中时,很多情况下会被隐式转化为一个指针,指向数组的首元素。注意这是在声明定长数组时,其数组名转换成的数组首地址是常量。而声明数组并使某个指针指向某个数组的地址(不一定是首元素),指针取值可以改变。
数组指针:
数组指针是指向数组首元素的地址的指针,其本质为指针(这个指针存放的是数组首元素的地址,相当于2级指针,这个指针不可以移动)
数组指针的构成形式为:类型名 (*p) [数组长度]
数组指针的使用:
int arr[10] = {0};
int (*p) [10] = &arr;
int * arr2[5] = {0};
int * (*p2) = &arr2;
int arr3[4] [5] ={0};
int (*p3) = &arr3[4] [5];
int (*p) [10];
//解释:p先和*结合说明p是一个指针变量,然后指向的是一个大小为10个整形的数组。所以p是一个指针,指向一个数组,叫数组指针。
//这里要注意:[]的优先级是要高于号的,所以必须()来保证p先和结合。
函数指针:
下面先来看一段代码:
可以看到这段代码运行结果。注意:在函数中函数名和&函数名都是函数的地址,为同一地址。
函数指针的应用
上面这段代码就是函数指针,函数指针就是指向函数的指针,
接下来我们看着一行代码:(*p)("hello bit.")
这里和p必须要加上括号,因为结合性的优先级,这样我们才能保证这里和p先结合,才能保证这是一个函数指针。而第二个参数部分的()表示函数调用符。而最后这里 *p只是为了表示这是一个指针,而指针指向的位置就是函数的位置,所以这里代码
(******p)("hello bit.")
p("hello bit.")
都为正确的函数指针。
函数指针数组:
int test(const char* str, int num)
{
}
int main()
{
int(*pf)(const char *str, int num) = test;//函数指针;
int(*arr[5])(const char*, int num);//函数指针数组;
int(*(*p)[5])(const char*, int);//指向函数指针数组的指针;
return 0;
}
通过上面的这段代码,我们总结得到:
函数指针:int (*p) (int,int)
那么在这上面代码修改就可以得到
函数指针数组:int (*p[5]) (int,int)
指向函数指针数组的指针:int (*(*p)[5]) (int,int)
通过上面的规律我们就很容易由一个函数指针写出函数指针数组以及指向函数指针数组的指针。
函数指针数组的应用 :
我们来看一段代码:
#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");
}
enum CALC
{
EXIT,
ADD,
SUB,
MUL,
DIV,
};
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;
}
void calc(int(*pfun)(int, int))
{
int ret = 0;
int x = 0;
int y = 0;
printf("请输入俩个操作数>: ");
scanf_s("%d%d", &x, &y);
ret = pfun(x, y);
printf("ret=%d\n", ret);
}
int main()
{
int(*pfun[5])(int, int) = { 0,Add,Sub,Mul,Div };//函数指针数组;
int input = 0;
do
{
menu();
printf("请选择>: ");
scanf_s("%d", &input);
if (input >= 1 && input <= 4)
{
calc(pfun[input]);
}
else
{
printf("非法\n");
}
/*switch (input)
{
case ADD:
ret = Add(x, y);
break;
case SUB:
ret = Sub(x, y);
break;
case MUL:
ret = Mul(x, y);
break;
case DIV:
ret = Div(x, y);
break;
case EXIT:
printf("退出\n");
break;
default:
printf("选择错误\n");
break;
}*/
} while (input);
system("pause");
return 0;
}
然后这段代码运行的结果如下图:
从上面这段代码以及运行结果我们就很容易看出这个函数指针数组的使用直接代替掉了这个switch语句在这个简单的计算器中的作用,使程序显得更加的简洁。
指向函数指针数组的指针:
指向函数指针数组的指针是一个 指针,指针指向一个数组,数组的元素都是函数指针;
* char ( * ( * a)[4])(char *p)
; 这个指针指向包含了4个元素的数组;这个数组里面存的是指向函数的指针;这个指针指向一些返回值类型为指向字符的指针,参数为指向字符的指针的函数。