在C中,比如 普通数据指针 (int*、char*等),我们可以有指向函数的指针。下面是一个简单的示例,展示了使用函数指针进行声明和函数调用。
#include <stdio.h> // A normal function with an int parameter // and void return type void fun( int a) { printf ( "Value of a is %d" , a); } int main() { // fun_ptr is a pointer to function fun() void (*fun_ptr)( int ) = &fun; /* The above line is equivalent of following two void (*fun_ptr)(int); fun_ptr = &fun; */ // Invoking fun() using fun_ptr (*fun_ptr)(10); return 0; } |
输出:
Value of a is 10
为什么我们需要在函数指针周围加一个括号,比如上面例子中的fun_ptr? 如果我们去掉括号,那么表达式“void(*fun_ptr)(int)”就变成了“void*fun_ptr(int)”,这是一个返回void指针的函数的声明。详情请参见下面的帖子。 如何声明指向函数的指针?
下面是一些关于函数指针的有趣事实。
1) 与普通指针不同,函数指针指向代码,而不是数据。通常,函数指针存储可执行代码的开头。
2) 与普通指针不同,我们不使用函数指针分配内存。
3) 函数名也可以用来获取函数的地址。例如,在下面的程序中,我们删除了赋值中的地址运算符“&”。我们还通过删除*改变了函数调用,程序仍然有效。
#include <stdio.h> // A normal function with an int parameter // and void return type void fun( int a) { printf ( "Value of a is %d" , a); } int main() { void (*fun_ptr)( int ) = fun; // & removed fun_ptr(10); // * removed return 0; } |
输出:
Value of a is 10
4) 和普通指针一样,我们可以有一个函数指针数组。下面第5点中的示例显示了指针数组的语法。
5) 功能指针可以用来代替开关盒。例如,在下面的程序中,要求用户在0和2之间进行选择,以执行不同的任务。
#include <stdio.h> void add( int a, int b) { printf ( "Addition is %d" , a+b); } void subtract( int a, int b) { printf ( "Subtraction is %d" , a-b); } void multiply( int a, int b) { printf ( "Multiplication is %d" , a*b); } int main() { // fun_ptr_arr is an array of function pointers void (*fun_ptr_arr[])( int , int ) = {add, subtract, multiply}; unsigned int ch, a = 15, b = 10; printf ( "Enter Choice: 0 for add, 1 for subtract and 2 " "for multiply" ); scanf ( "%d" , &ch); if (ch > 2) return 0; (*fun_ptr_arr[ch])(a, b); return 0; } |
Enter Choice: 0 for add, 1 for subtract and 2 for multiply 2 Multiplication is 150
6) 与普通数据指针一样,函数指针可以作为参数传递,也可以从函数返回。 例如,考虑下面的C程序,其中WrPopPee()接收一个空函数()作为参数并调用传递函数。
// A simple C program to show function pointers as parameter #include <stdio.h> // Two simple functions void fun1() { printf ( "Fun1" ); } void fun2() { printf ( "Fun2" ); } // A function that receives a simple function // as parameter and calls the function void wrapper( void (*fun)()) { fun(); } int main() { wrapper(fun1); wrapper(fun2); return 0; } |
这一点在C语言中特别有用。在C语言中,我们可以使用函数指针来避免代码冗余。例如,一个简单的 qsort() 函数可用于按升序或降序对数组进行排序,如果是结构数组,则可按任何其他顺序进行排序。不仅如此,对于函数指针和void指针,还可以对任何数据类型使用qsort。
// An example for qsort and comparator #include <stdio.h> #include <stdlib.h> // A sample comparator function that is used // for sorting an integer array in ascending order. // To sort any array for any other data type and/or // criteria, all we need to do is write more compare // functions. And we can use the same qsort() int compare ( const void * a, const void * b) { return ( *( int *)a - *( int *)b ); } int main () { int arr[] = {10, 5, 15, 12, 90, 80}; int n = sizeof (arr)/ sizeof (arr[0]), i; qsort (arr, n, sizeof ( int ), compare); for (i=0; i<n; i++) printf ( "%d " , arr[i]); return 0; } |
输出:
5 10 12 15 80 90
与qsort()类似,我们可以编写自己的函数,这些函数可以用于任何数据类型,并且可以在没有代码冗余的情况下执行不同的任务。下面是一个可用于任何数据类型的搜索函数示例。实际上,我们可以通过编写一个定制的比较函数,使用这个搜索函数来查找接近的元素(低于阈值)。
#include <stdio.h> #include <stdbool.h> // A compare function that is used for searching an integer // array bool compare ( const void * a, const void * b) { return ( *( int *)a == *( int *)b ); } // General purpose search() function that can be used // for searching an element *x in an array arr[] of // arr_size. Note that void pointers are used so that // the function can be called by passing a pointer of // any type. ele_size is size of an array element int search( void *arr, int arr_size, int ele_size, void *x, bool compare ( const void * , const void *)) { // Since char takes one byte, we can use char pointer // for any type/ To get pointer arithmetic correct, // we need to multiply index with size of an array // element ele_size char *ptr = ( char *)arr; int i; for (i=0; i<arr_size; i++) if (compare(ptr + i*ele_size, x)) return i; // If element not found return -1; } int main() { int arr[] = {2, 5, 7, 90, 70}; int n = sizeof (arr)/ sizeof (arr[0]); int x = 7; printf ( "Returned index is %d " , search(arr, n, sizeof ( int ), &x, compare)); return 0; } |
输出:
Returned index is 2
通过编写一个单独的自定义比较(),上述搜索函数可用于任何数据类型。
7) C++中的许多面向对象特性是用C.中的函数指针实现的。 虚拟函数 .类方法是使用函数指针实现的另一个示例。参考 这本书 更多细节。
相关文章: C和C++中的指针集1(介绍、算术和数组)
参考资料: http://www.cs.cmu.edu/~ab/15-123S11/AnnotatedNotes/讲师14。pdf
http://www.cs.cmu.edu/~guna/15-123S11/讲座/讲座14。pdf
本文由 阿比拉蒂 。如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请发表评论。