在C语言中:指针是C语言的特色,有着各种各样的指针,普通的变量指针,常量指针,数组指针,指针数组,函数指针,指针函数。我们就讲一下函数指针与回调函数吧
首先关于函数指针,其实很简单。
对于一个函数指针来说,顾名思义,就是一个指向函数的指针,需要知道的是,对于指针而言,他总是存储一块地址,地址里面有着一个,一组,或者一块数据,在函数中,函数的存储是放在代码段的,每个函数都有着一个函数首地址,调用了这个地址相当于调用的这个函数。
具体的可以观看我的这篇博客,其中就通过在内存阶段改变栈帧返回值,成功的调用了一个重启函数。浅谈栈帧(一)
其实C++特性中的虚函数表就有利用这一点。
所以说呢,函数指针就是一个指向函数首地址的指针,好了,先了解这个定义,然后我们进入下一个阶段。
对于指针,他不仅仅要指向一个具体的量,他还需要其他的标识符来描述这个量的具体属性。
例如:char* str,void *func(int,int);
在指针符号*的左右,都是在描述这个指针的具体信息。
那么对于函数指针而言,这是怎么样的呢。
void (*f) ( );虽然()的优先级高于*,但由于有括号存在,首先执行的是解引用,所以f是一个指针;接下来执行( ),表明f指向一个函数,这个函数不返回任何值。现在得出结论:f是一个指向不接受参数且不返回任何值的函数的指针,简称函数指针(pointer to function)。
<1>.初始化
注意指向函数的指针(函数指针)指向的是函数而非普通的变量,它所指向的函数也是有特定类型的,函数的类型由它的返回值类型以及形参列表确定,和函数名无关。对函数指针初始化时可以采用相同类型函数的函数名或函数指针(当然还有零指针常量)。假如有函数void test ( ),int wrong_match (int)和函数指针void (*ptf) ( )。
下面的初始化是错误的,因为函数指针的类型与函数的类型不匹配:
f = wrong_match;
f = & wrong_match;
ptf = wrong_match;
ptf = & wrong_match;
以下初始化及赋值是合法的:
f = test;
f = &test;
ptf = test;
ptf = &test;
f = pf;
要做出解释的是test和&test都可以用来初始化函数指针。C语言规定函数名会被转换为指向这个函数的指针,除非这个函数名作为& 操作符或sizeof操作符的操作数(注意:函数名用于sizeof的操作数是非法的)。也就是说f = test;中test被自动转换为&test,而f= &test;中已经显示使用了&test,所以test就不会再发生转换了。因此直接引用函数名等效于在函数名上应用 & 运算符,两种方法都会得到指向该函数的指针。
int (*function(int)) (double*,char);要了解此声明的含义,首先来看function(int),将function声明为一个函数,它带有一个int型的形式参数,这个函数的返回值为一个指针,正是我们本将开头讲过的函数指针int (*) (double*, char);这个指针指向一个函数,此函数返回int型并带有两个分别是double*型和char型的形参。如果使用typedef可以将这个声明简化:
typedef int (*ptf) (double*, char);
ptf function(int );
总结:
其实对于函数指针来说。我们只需要记住。从最中间括号开始往外逐步分析,函数指针是(*)
而指针函数是(*()),懂得会分区,就知道函数指针是什么东西了。弄清楚他本身名字,然后弄清楚他的描述情况。
回调函数:
上面已经说清楚了对于函数指针而言,他有着他自己的名字,有着相对于的描述信息,信息不一样的无法进行赋值配对,然后既然有函数指针这种东西?那么他出现是干什么用的呢?
其实对于函数指针,无非就是让我们在面临不同情况去使用他。函数指针指向不同的情况,来进行不同的操作,在主题函数处理中提供不同的函数指针借口,借此来处理不同的情况。
在计算机程序设计中,回调函数,或简称回调(Callback 即call then back 被主函数调用运算后会返回主函数),是指通过函数参数传递到其它代码的,某一块可执行代码的引用。这一设计允许了底层代码调用在高层定义的子程序。
来看一个简单例子:
#include <stdio.h> int int_cmp(const void * p1, const void * p2) { if (*( int *)p1 > *(int *) p2) { return 1; } else if (*( int *)p1 == *(int *) p2) { return 0; } else { return -1; } } void _swap(void *p1, void * p2, int size) { int i = 0; for (i = 0; i< size; i++) { char tmp = *((char *)p1 + i); *(( char *)p1 + i) = *((char *) p2 + i); *(( char *)p2 + i) = tmp; } } void bubble(void *base, int count , int size, int(*cmp )(void *, void *)) { int i = 0; int j = 0; for (i = 0; i< count - 1; i++) { for (j = 0; j<count - i - 1; j++) { if (cmp ((char *) base + j*size , (char *)base + (j + 1)*size) > 0) { _swap(( char *)base + j*size, (char *)base + (j + 1)*size, size); } } } } int main() { int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 }; //char *arr[] = {"aaaa","dddd","cccc","bbbb"}; int i = 0; bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp); for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++) { printf( "%d ", arr[i]); } printf("\n"); return 0; }
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。