C语言 函数指针
- 概念
- 在C语言中,函数指针是一种特殊的指针类型,它指向的是函数而不是普通的数据变量。函数在内存中有其入口地址,函数指针就是用来存储这个地址的变量。
- 函数指针的定义
- 函数指针的定义形式如下:
- 返回值类型 (*指针变量名)(参数类型列表);
- 例如,定义一个指向返回值为
int
,参数为int
和int
的函数的指针:int (*funcPtr)(int, int);
- 这里
funcPtr
就是一个函数指针变量,它可以指向任何返回值为int
且有两个int
类型参数的函数。
- 函数指针的定义形式如下:
- 函数指针的赋值与使用
- 赋值
- 可以将一个函数的地址赋给函数指针。例如:
int add(int a, int b) { return a + b; } int main() { int (*funcPtr)(int, int) = add; // 或者 int (*funcPtr)(int, int); funcPtr = add; return 0; }
- 可以将一个函数的地址赋给函数指针。例如:
- 使用函数指针调用函数
- 一旦函数指针被赋值,就可以通过函数指针来调用它所指向的函数。有两种方式:
- 直接使用函数指针变量调用:
int add(int a, int b) { return a + b; } int main() { int (*funcPtr)(int, int) = add; int result = funcPtr(3, 5); printf("Result: %d\n", result); return 0; }
- 也可以将函数指针作为函数参数传递,在另一个函数中调用:
int add(int a, int b) { return a + b; } void callFunction(int (*funcPtr)(int, int), int num1, int num2) { int result = funcPtr(num1, num2); printf("Result: %d\n", result); } int main() { callFunction(add, 3, 5); return 0; }
- 直接使用函数指针变量调用:
- 一旦函数指针被赋值,就可以通过函数指针来调用它所指向的函数。有两种方式:
- 赋值
- 函数指针数组
- 可以定义函数指针数组,这在需要根据不同情况调用不同函数时非常有用。例如:
int add(int a, int b) { return a + b; } int subtract(int a, int b) { return a - b; } int multiply(int a, int b) { return a * b; } int main() { int (*funcArray[])(int, int) = {add, subtract, multiply}; int result = funcArray[1](5, 3); printf("Result: %d\n", result); return 0; }
- 在这个例子中,
funcArray
是一个函数指针数组,它包含了add
、subtract
和multiply
三个函数的指针。通过funcArray[1]
选择subtract
函数的指针,然后调用subtract(5, 3)
得到结果。
- 可以定义函数指针数组,这在需要根据不同情况调用不同函数时非常有用。例如:
- 函数指针作为函数返回值
- 函数可以返回函数指针。例如:
int add(int a, int b) { return a + b; } int subtract(int a, int b) { return a - b; } int (*selectFunction(int choice))(int, int) { if (choice == 0) { return add; } else { return subtract; } } int main() { int (*funcPtr)(int, int); funcPtr = selectFunction(1); int result = funcPtr(5, 3); printf("Result: %d\n", result); return 0; }
- 在这个例子中,
selectFunction
函数根据传入的choice
参数返回add
函数或subtract
函数的指针,然后在main
函数中使用这个返回的函数指针调用相应的函数。
- 函数可以返回函数指针。例如:
- 用途
- 回调函数
- 函数指针常用于实现回调函数机制。例如,在一个排序算法函数中,可以将一个比较函数的指针作为参数传入。这样用户就可以根据自己的需求定义不同的比较函数,实现不同的排序逻辑。
- 事件驱动编程
- 在事件驱动的程序中,函数指针可以用来指向不同的事件处理函数。当某个事件发生时,通过函数指针调用相应的处理函数。
- 实现多态性(类似概念在C语言中的体现)
- 虽然C语言没有像面向对象语言那样的多态性,但函数指针可以在一定程度上实现类似的功能。例如,通过函数指针数组,可以根据不同的情况调用不同的函数,类似于多态性中的根据对象类型调用不同的方法。
- 回调函数
-
如何使用函数指针调用函数
- 直接调用
- 首先,定义一个函数指针并将其指向一个函数。例如,有一个函数
int add(int a, int b)
,定义函数指针并赋值如下:int (*funcPtr)(int, int) = add;
- 然后,可以使用函数指针直接调用函数:
int result = funcPtr(3, 5);
- 首先,定义一个函数指针并将其指向一个函数。例如,有一个函数
- 作为函数参数调用
- 定义一个函数,该函数接受一个函数指针作为参数。例如:
void callFunction(int (*funcPtr)(int, int), int num1, int num2) { int result = funcPtr(num1, num2); printf("Result: %d\n", result); }
- 在调用这个函数时,将实际的函数名作为参数传入:
int add(int a, int b) { return a + b; } int main() { callFunction(add, 3, 5); return 0; }
- 定义一个函数,该函数接受一个函数指针作为参数。例如:
- 直接调用
-
如何通过函数指针访问结构体成员(假设函数指针指向的函数操作结构体)
- 首先定义一个结构体和操作该结构体的函数。例如:
struct Point { int x; int y; }; int getX(struct Point *p) { return p->x; }
- 然后定义函数指针并赋值:
int (*funcPtr)(struct Point *); funcPtr = getX;
- 在使用函数指针时,传入结构体指针参数:
struct Point p = {3, 5}; int result = funcPtr(&p);
- 这里通过函数指针
funcPtr
调用getX
函数,getX
函数通过传入的结构体指针p
访问结构体成员x
。
- 首先定义一个结构体和操作该结构体的函数。例如:
-
函数指针与数组指针的区别
- 指向的对象不同
- 函数指针:指向的是函数的入口地址。函数指针的定义形式为
返回值类型 (*指针变量名)(参数类型列表)
,例如int (*funcPtr)(int, int)
,它指向的是一个接受两个int
参数并返回int
值的函数。 - 数组指针:指向的是数组。数组指针的定义形式为
数据类型 (*指针变量名)[数组大小]
,例如int (*arrPtr)[5]
,它指向的是一个包含5个int
元素的数组。
- 函数指针:指向的是函数的入口地址。函数指针的定义形式为
- 指针运算不同
- 函数指针:函数指针的指针运算在标准C中没有定义(因为函数在内存中的布局不是像数组那样连续存储元素的形式)。虽然在某些编译器下可能有一些特定的实现,但从标准角度看,不应该对函数指针进行算术运算(如
++
、--
等)。 - 数组指针:数组指针可以进行指针运算。例如,如果
arrPtr
是一个指向包含5个int
元素数组的指针,那么arrPtr + 1
将指向内存中紧接着当前数组的下一个包含5个int
元素的数组(假设数组在内存中是连续存储的)。
- 函数指针:函数指针的指针运算在标准C中没有定义(因为函数在内存中的布局不是像数组那样连续存储元素的形式)。虽然在某些编译器下可能有一些特定的实现,但从标准角度看,不应该对函数指针进行算术运算(如
- 用途不同
- 函数指针:主要用于实现回调函数、函数表(函数指针数组)等功能,用于在不同的代码模块之间传递函数的调用关系,实现类似于多态的行为。例如,在排序算法中传入比较函数指针,以实现不同的排序逻辑。
- 数组指针:用于处理多维数组(特别是不规则的多维数组)或者在函数参数传递中传递数组的地址而不丢失数组的维数信息。例如,在处理矩阵运算时,使用数组指针可以方便地遍历矩阵。
- 指向的对象不同