在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。
文章目录
定义函数指针
因为指针存储的值是一块内存地址,而函数也是在内存的某个地址中,所以,当一个指针指向的内存地址指的是一个函数的话,这种指针被称为函数指针。
定义一个函数指针取决于被指向的函数的函数返回类型和参数列表。例如,有函数的定义如下:
int max(int x, int y) {
return x > y ? x : y
}
则定义一个指针指向该函数的写法是:
int (*p)(int, int) = &max;
声明函数指针需要注意的事项:
- 指针对应的数据类型必须与函数返回值一致
- 指针参数列表必须与函数参数列表中的数据类型的顺序一致,不需要形参
直接看一个案例,会更容易理解函数指针的定义
#include<stdio.h>
// 声明函数
int fun1();
int fun2(int x, double y);
double fun3(int x, double y, int z, long i);
void fun4(int x);
void fun5(double x, int* p);
int* fun6(int x);
int main() {
// 声明函数指针
int (*p1)() = &fun1;
int (*p2)(int, double) = &fun2;
double (*p3)(int, double, int, long) = &fun3;
void (*p4)(int) = &fun4;
void (*p5)(double, int*) = &fun5;
int* (*p6)(int) = &fun6;
return 0;
}
// 定义函数
int fun1(){return 0;}
int fun2(int x, double y){return 0;}
double fun3(int x, double y, int z, long i){return 0.0;}
void fun4(int x){}
void fun5(double x, int* p){}
int* fun6(int x){return NULL;}
把函数指针看作是一个函数的影子,使其以变量的形式存在于程序中,进而可以到处被传递或者运用。换句话说,函数指针既能像函数一样被使用,又能像变量那样被传递。如下例所示:
#include<stdio.h>
void print(const char * cs) {
printf("%s\n", cs);
}
int main() {
void (*p)(const char*) = &print;
p("Hello World!");
return 0;
}
执行结果:
Hello World!
再来一个有返回的小案例:
#include<stdio.h>
int max(int x, int y);
int main() {
int rm, rp, a = 10, b = 3;
int (*p)(int, int) = &max;
rm = max(a, b);
printf("max(%d, %d) = %d\n", a, b, rm);
rp = p(a, b);
printf("p(%d, %d) = %d\n", a, b, rp);
return 0;
}
int max(int x, int y) {
return x > y ? x : y;
}
执行结果:
max(10, 3) = 10
p(10, 3) = 10
函数指针作为某个函数的参数
一旦某个指针指向了一个函数后,当该指针以变量的形式传递到某个函数中,那么是能够在目标函数内调用该指针指向的函数的。案例代码如下所示:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define SIZE 6
/**
* 求两个数的最大值
*/
int max(int x, int y);
/**
* 得到一个随机的数组指针
*/
int * randArray();
/**
* 求一个数组中最大的数字
* @param array 指针数组
* @param size 数组大小
* @param *p 求最大值的函数
*/
int maxInArray(int *array, int size, int (*p)(int, int));
int main() {
int i, mv;
int * (*p)() = &randArray;
int (*m)(int, int) = &max;
// p() 等价于 randArray();
int *ns = p();
for(i = 0; i < SIZE; i++, ns++) {
printf("*ns[%d]=%d.\n", i, *ns);
}
// 当遍历结束后, ns 指向的是数组最后一个元素, 需要将其重置到索引为零的指针处
for(i = SIZE; i > 0; i--) {
ns--;
}
// mv = maxInArray(ns, SIZE, &max);
mv = maxInArray(ns, SIZE, m);
printf("max number is %d in array.\n", mv);
return 0;
}
/**
* 求两个数的最大值
*/
int max(int x, int y) {
return x > y ? x : y;
}
/**
* 得到一个随机的数组指针
*/
int * randArray() {
static int nums[SIZE];
srand((unsigned)time(NULL));
for(int i = 0; i < SIZE; i++){
nums[i] = rand();
}
return nums;
}
/**
* 求一个数组中最大的数字
* @param array 指针数组
* @param size 数组大小
* @param *p 求最大值的函数
*/
int maxInArray(int *array, int size, int (*p)(int, int)) {
int m = 0, i = 0;
for(int i = 0; i < size; i++, array++) {
// p(1, 2) 等价于 max(1, 2)
m = p(m, *array);
}
return m;
}
执行结果:
*ns[0]=13213.
*ns[1]=23737.
*ns[2]=15703.
*ns[3]=17692.
*ns[4]=14498.
*ns[5]=26241.
max number is 26241 in array.
本例中,指针 p 和指针 m 都是函数指针,函数指针 p 在 main 函数中被调用,并返回一个数组指针,最后将返回的数组指针 和指针 m 都传递到 maxInArray 函数中,并在函数 maxInArray 中调用指针 m 指向的函数得到最终的结果。