【C语言】函数指针与回调函数

在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;
}



本文出自 “剩蛋君” 博客,请务必保留此出处http://memory73.blog.51cto.com/10530560/1771227

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值