第十一章:高级指针-1函数指针

C函数指针

目标

在本文章中,您将学习C函数指针,这是一种特殊的指针,它指向函数而不是数据对象。

C函数指针的定义

函数指针是指向函数地址的指针。

C函数指针语法

下面演示了声明函数指针的语法:

< 返回类型 > (* < 指针名 >) (函数参数);

声明函数指针的语法与声明函数的语法类似。唯一的区别是,不是使用函数名,而是使用圆括号()中的指针名。

让我们更详细地检查上面的函数指针语法:

首先,指定函数指针的返回类型。它可以是任何有效类型,如int、float、char或void。
其次,将函数指针的名称放在括号内。按照约定,函数指针的名称以fp开头。
第三,用相应的类型指定函数的所有参数。注意,函数指针只能引用具有相同签名的函数。它意味着函数指针所指向的所有函数必须具有相同的返回类型和形参。
下面的例子声明了一个函数指针,该指针指向一个接受两个整型参数并返回一个整型数的函数。

int (*fpFunc)(int x,int y); // 声明一个函数指针

使用函数指针

在使用函数指针之前,你需要给它分配一个函数的地址。

首先,假设您有一个compare()函数,它接受两个整数a和b。如果a > b, compare()函数返回1,如果a = b,返回0,如果a < b,返回-1。

下面是compare()函数的声明和实现:

int compare(int,int);

/*
    目的: 比较x和y
    返回 1 如果 x > y, -1 如果 x < y , 0 如果 x = y */ 
int compare(int x,int y) 
{
      if(x > y)
         return 1;
      if(x < y )
        return -1;
    return 0;
}

接下来,我们声明一个函数指针,该指针指向compare()函数:

int (*fpComparer)(int x,int y);

然后,在main()函数内部,可以将compare()函数的地址赋值给函数指针:

fpComparer =&compare;

注意,一元操作符&是可选的。然而,为了使代码更易于移植,当将函数的地址赋给函数指针时,应该始终使用一元操作符(&)。

最后,我们可以使用函数指针调用函数,如下所示:

result = (*fpComparer)(a,b);

全部放在一起。

#include <stdio.h>
#include <stdlib.h> 

/* 声明一个函数指针 */
int (*fpComparer)(int x,int y);

int compare(int,int);

int main()
{
    int result;
    int a = 10;
    int b = 20;
    char* msg;

    fpComparer = &compare;

    result = (*fpComparer)(a,b);

    switch(result)
    {
    case 1:
        printf("a大于b");
        break;
    case -1:
        printf("a小于b");
        break;
    case 0:
        printf("a等于b");
        break;
    }

    return 0;
}
/*
    目的: 比较x和y
    返回 1 如果 x > y, -1 如果 x < y , 0 如果 x = y */ 
int compare(int x,int y) 
{
      if(x > y)
         return 1;
      if(x < y )
        return -1;
    return 0;
}

将函数指针作为参数传递给函数

你可以将函数指针作为参数传递给函数。这允许您使代码更加灵活。使用函数指针作为参数的一个经典例子是函数库中的qsort()函数。函数的作用是:使用快速排序算法对任意类型的数组进行排序。

下面的示例演示如何使用qsort()函数对整数数组进行排序。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int compare_int(const int * x,const int * y);

int (*fpComparer)(const void *p, const void *q);

int main()
{
    int i;
    // 排序整型数组
    int int_arr[] = { 7, 3, 4, 1, -1, 23, 12, 43, 2, -4, 5 };

    size_t len = sizeof(int_arr)/sizeof(int);

    fpComparer = &compare_int;

    qsort(int_arr, len, sizeof(int), (*fpComparer));

    // 打印排序后的数组
    for(i = 0; i < len; i++)
    {
        printf("%d ",int_arr[i]);
    }
    printf("\n");

}

int compare_int(const int * x,const int * y)
{
    if (*x == *y)
        return 0;
    else if (*x < *y)
        return -1;
    else
        return 1;
}

返回函数指针的函数

函数可以返回函数指针。让我们看一下下面的例子:

#include <stdio.h>
#include <stdlib.h>

/* 定义函数指针类型 */
typedef int(*pfOperator)(int, int);

int plus(int,int);
int minus(int,int);

pfOperator getOperator(const char oper);

int main()
{
    int x = 10,
        y = 20,
        z = 0;

    pfOperator func = NULL;

    func = getOperator('+');
    z = func(x,y);
    printf("%d\n",z);

    func = getOperator('-');
    z = func(x,y);
    printf("%d\n",z);

    return 0;
}

pfOperator getOperator(const char oper)
{
    switch(oper)
    {
    case '+':
        return plus;
        break;
    case '-':
        return minus;
        break;
    default:
        return NULL;
    }
}

int plus(int x,int y)
{
    return x + y;
}
int minus(int x,int y)
{
    return x - y;
}

函数指针数组

函数指针数组包括具有相同签名的所有函数指针。函数指针数组允许您选择在运行时执行哪个函数。

下面的示例演示如何使用函数指针数组。

#include <stdio.h>
#include <stdlib.h>

/* define function pointer type */
typedef int(*pfOperator)(int, int);

int plus(int,int);
int minus(int,int);

pfOperator getOperator(const char oper);

int main()
{
    int x = 10,
        y = 20,
        z = 0;
    // 声明函数指针数组
    pfOperator funcs[2];

    funcs[0] = getOperator('+');
    z = (funcs[0])(x,y);
    printf("%d\n",z);

    funcs[1] = getOperator('-');
    z = (*funcs[1])(x,y);
    printf("%d\n",z);

    return 0;
}

pfOperator getOperator(const char oper)
{
    switch(oper)
    {
    case '+':
        return plus;
        break;
    case '-':
        return minus;
        break;
    default:
        return NULL;
    }
}
int plus(int x,int y)
{
    return x + y;
}
int minus(int x,int y)
{
    return x - y;
}

总结

  • 在本文章中,我们讨论了C函数指针,并向您展示了如何使用函数指针使代码更加灵活。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容