玖富娱乐平台全网唯一指定1956注册开户网站

搞懂C言语函数指针_玖富娱乐主管发布

日期:2019-01-04 浏览:
玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。

 

媒介

函数指针是甚么?怎样运用函数指针?函数指针到底有甚么大用?本文将逐一引见。

怎样明白函数指针

如果有int *范例变量,它存储的是int范例变量的地点;那末关于函数指针来讲,它存储的就是函数的地点。函数也是有地点的,函数现实上由载入内存的一些指令构成,而指向函数的指针存储了函数指令的肇端地点。云云看来,函数指针并没有甚么迥殊的。我们能够检察顺序中函数的地点:

#include <stdio.h>
int test()
{
    printf("this is test function");
    return 0;
}
int main(void)
{
    test();
    return 0;
}

编译:

gcc -o testFun testFun.c

检察test函数相对地点(并不是现实运转时的地点):

$ nm testFun |grep test  #检察test函数的符号表信息
0000000000400526 T test

怎样声明函数指针

声明一般范例指针时,须要指明指针所指向的数据范例,而声明函数指针时,也就要指明指针所指向的函数范例,即须要指明函数的返回范例和形参范例。比方关于下面的函数原型:

int sum(int,int);

它是一个返回值为int范例,参数是两个int范例的函数,那末怎样声明该范例函数的指针呢?很简朴,将函数名替换成(*pf)情势便可,即我们把sum替换成(*fp)便可,fp为函数指针名,效果以下:

int (*fp)(int,int);

如许就声清晰明了和sum函数范例雷同的函数指针fp。这里申明两点,第一,*和fp为一体,说清晰明了fp为指针范例,第二,*fp须要用括号括起来,不然就会酿成下面的状况:

int *fp(int,int);

这类状况下,意义就天差地别了,它声清晰明了一个参数为两个int范例,返回值为int范例的指针的函数,而不再是一个函数指针了。

在常常运用函数指针以后,我们很快就会发明,每次声明函数指针都要带上长长的形参和返回值,异常未便。这个时刻,我们应当想到运用typedef,即为某范例的函数指针起一个别号,运用起来就轻易许多了。比方,关于前面提到的函数能够运用下面的体式格局声明:

typedef int (*myFun)(int,int);//为该函数指针范例起一个新的名字
myFun f1;       //声明myFun范例的函数指针f1

上面的myFun就是一个函数指针范例,在其他处所就能够很轻易地用来声明变量了。typedef的运用不在本文的议论局限,然则迥殊强调一句,typedef中声明的范例在变量名的地位涌现,明白了这一句,也就很轻易运用typedef了。因而下面的体式格局是毛病的:

typedef myFun (int)(int,int);   //毛病
typedef (int)(int,int)  *myFun;   //毛病

为函数指针赋值

赋值也很简朴,既然是指针,将对应指针范例赋给它既可。比方:

-玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。-
#include<stdio.h>
int test(int a,int b)
{
    /*do something*/
    return 0
}
typedef int(*fp)(int,int);
int main(void)
{
    fp f1 = test; //表达式1
    fp f2 = &test;//表达式2
    printf("%pn",f1);
    printf("%pn",f2);
    return 0;
}

在这里,声清晰明了返回范例为int,接收两个int范例参数的函数指针f1和f2,离别给它们举行了赋值。表达式1和表达式2在作用上并没有甚么区别。由于函数名在被运用时老是由编译器把它转换为函数指针,而前面加上&不外显式的说清晰明了这一点而已。

挪用

挪用也很轻易,把它算作一个一般的函数名便可:

#include<stdio.h>
int test(int a,int b)
{
    /*do something*/
    printf("%d,%dn",a,b);
    return 0
}
typedef int(*fp)(int,int);
int main(void)
{
    fp f = test; 
    f(1,2);//表达式1
    (*f)(3,4);//表达式2
    return 0;
}

在函数指针背面加括号,并传入参数便可挪用,个中表达式1和表达式2好像都能够胜利挪用,然则哪一个是准确的呢?ANSI C以为这两种情势等价。

函数指针有何用

函数指针的运用场景对照多,以库函数qsort排序函数为例,它的原型以下:

void qsort(void *base,size_t nmemb,size_t size , int(*compar)(const void *,const void *));

看起来很庞杂对不对?拆开来看以下:

void qsort(void *base, size_t nmemb, size_t size, );

拿掉第四个参数后,很轻易明白,它是一个无返回值的函数,接收4个参数,第一个是void*范例,代表原始数组,第二个是size_t范例,代表数据数目,第三个是size_t范例,代表单个数据占用空间巨细,而第四个参数是函数指针。这第四个参数,即函数指针指向的是甚么范例呢?

int(*compar)(const void *,const void *)

很显然,这是一个接收两个const void*范例入参,返回值为int的函数指针。
到这里也就很清晰了。这个参数通知qsort,应当运用哪一个函数来对照元素,即只需我们通知qsort对照巨细的划定规矩,它就能够帮我们对恣意数据范例的数组举行排序。

在这里函数指针作为了参数,而他一样能够作为返回值,建立数组,作为构造体成员变量等等,它们的详细运用我们在背面的文章中会引见,本文不作睁开。本文只引见一个简朴实例。

实例引见

我们经由过程一个实例来看函数指针怎样运用。假设有一门生信息,须要依照门生结果举行排序,该怎样处置惩罚呢?

#include <stdio.h>
#include <stdlib.h>
#define STU_NAME_LEN 16
/*门生信息*/
typedef struct student_tag
{
    char name[STU_NAME_LEN];  //门生姓名
    unsigned int id;          //门生学号
    int score;                //门生结果
}student_t;
int studentCompare(const void *stu1,const void *stu2)
{
  /*强转成须要对照的数据构造*/
    student_t *value1 = (student_t*)stu1;
    student_t *value2 = (student_t*)stu2;
    return value1->score-value2->score;
}
int main(void)
{
    /*建立三个门生信息*/
    student_t stu1 = {"one",1,99};
    student_t stu2 = {"two",2,77};
    student_t stu3 = {"three",3,88};

    student_t stu[] = {stu1,stu2,stu3};

    /*排序,将studentCompare作为参数传入qsort*/
    qsort((void*)stu,3,sizeof(student_t),studentCompare);
    int loop = 0;

    /**遍历输出*/
    for(loop = 0; loop < 3;loop )
    {
        printf("name:%s,id:%u,score:%dn",stu[loop].name,stu[loop].id,stu[loop].score);
    }
    return 0;
}

我们建立了一个门生信息构造,构造成员包孕名字,学号和结果。main函数中建立了一个包罗三个门生信息的数组,并运用qsort函数对数组依照门生结果举行排序。qsort函数第四个参数是函数指针,因而我们须要传入一个函数指针,而且这个函数指针的入参是cont void *范例,返回值为int。我们经由过程前面的进修知道了函数名自身就是指针,因而只须要将我们本身完成的studentCompare作为参数传入便可。

终究运转效果以下:

name:two,id:2,score:77
name:three,id:3,score:88
name:one,id:1,score:99

能够看到,终究门生信息依照分数从低到高输出。

总结

本文引见了函数指针的声明和简朴运用。更多运用将在背面的文章引见,本文总结以下:

  • 函数指针与其他指针范例无素质差别,不外它指向的是函数的地点而已。
  • 声明函数指针须要指明函数的返回范例和形参范例。
  • 函数名在被运用时老是由编译器把它转换为函数指针。
  • 要想声明函数指针,只需写出函数原型,然后将函数名用(*fp)替代便可。这里fp是声明的函数指针变量。
  • typedef中声明的范例在变量名的地位涌现。

微信民众号【编程珠玑】:专注但不限于分享计算机编程基本,Linux,C言语,C ,Python,数据库等编程相干[原创]技术文章,号内包罗大批典范电子书和视频进修资本。迎接一同交流进修,一同修炼计算机“内功”,知其然,更知其所以然。

-玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。


平台知识

联系方式丨CONTACT

  • 全国热线:7711177
  • 传真热线:010-88888888
  • Q Q咨询:7711177
  • 企业邮箱:
首页
电话
短信