惧留孙网

juliusun.com

在线教程 > C语言教程 > 函数指针

函数指针

第 34/50 节 冥河C语言教程


指针不光可以指向基本变量,还可以指向函数,本节称指向函数的指针为函数指针。

函数经过编译后,也会占用内存空间。与变量不同的是,函数占用的空间存储有可执行的指令,而不像变量只存放数据。调用函数时,只要知道函数入口地址即可。C语言规定,函数名就是函数入口地址。这一点与数组有点类似,数组名是数组首地址。

函数指针定义方式如下:

函数返回值类型 ( * 指针变量名 )( 参数列表 )

分析一下定义语法:由于星号*和指针变量名用小括号括起来,首先确定变量是指针类型。然后由后面的小括号(),确定指针指向的内容是函数。然后再通过参数列表和返回值确定指向函数参数和返回值。

在函数指针类型时,只要把指针变量名省略即可,即类型为:函数返回值类型 (*)(参数列表)。

函数指针类型确定后,只有函数参数列表和返回值全部与指针类型相同,才能赋值。

函数名是函数入口地址。直接写函数名,是调用函数,转向函数入口开始执行。用函数指针情况也是如此。使用函数指针不会降低效率。

函数指针进行自增自减运算是无意义的。函数指针可以根据情况不同,指向不同的函数。

注意区分一下,参数列表用小括号括起来,代表指针指向的是函数。如果参数列表用方括号[ ]括起来且里面是常量,说明指向的是数组而不是函数。编译器会根据符号来判断类型。

赋值方式为:

指针变量名 = 函数名

或:

指针变量名 = &函数名

不同编辑器对于赋值时是否需要在函数名前是否加取地址符&可能支持类型有所不同。

注意,赋值时只写函数名即可,无须添加括号及参数等。

调用指向的函数格式为:

( * 指针变量名 )( 参数列表 )

很多编译器支持调用指针指向的函数时不写星号,格式如下:

指针变量名( 参数列表 )

举例说明,完成一个函数destroy_data,功能是将某内存块数据清0。destroy_data有三个参数,按顺序分别是内存块地址、要清理的字节数、函数指针pf。函数当指针pf为调用传递的函数指针,指定进度报告函数。如果函数指针不为NULL,每完成一部分清理工作,就要调用一下pf指向的函数。pf指向的函数来向用户报告进度,方便用户规划等待时间。代码如下:


  1. #include<stdio.h>
  2. int main( )
  3. {
  4. void destroy_data(char *pdata,unsigned int size,void (*pfun)(unsigned int finished,unsigned total));
  5. void report(unsigned int size,unsigned all); //函数声明
  6. char password[50] = "123456";
  7. void (*pr)(unsigned int finished,unsigned total); //定义函数指针,返回类型及参数列表要与指向的函数一致
  8. pr = report; //函数指针赋值,注意,只要指明report函数名即可,不用写括号
  9. /*假设代码已经使用完毕,下面开始销毁内存数据,防止被非法入侵泄漏密码*/
  10. destroy_data(password,50,pr);
  11. getchar( ) ; //使程序暂停一下
  12. return 0;
  13. }
  14. void destroy_data(char *pdata,unsigned int size,
  15. void (*pfun)(unsigned int finished,unsigned total) /*定义函数指针类型*/) //函数头部太长,分成两行写
  16. {
  17. unsigned int all = size;
  18. while(0 != size)
  19. {
  20. *pdata = 0;
  21. ++pdata;
  22. --size;
  23. if(NULL != pfun) //判断函数指针是否为空
  24. (*pfun)( size , all ); //调用函数指针指向的函数,很多编译器也可以直接写成 pfun ( size , all );即省略星号
  25. }
  26. }
  27. void report(unsigned int size,unsigned all)
  28. {
  29. printf("总工作量为 %d 字节,还剩下 %d 字节,完成 %f %%\n",all, size , 100 - ((float)size)/all*100 );
  30. //输出完成进度。整数相除只会保留整数部分,所以转化为float类型
  31. }

最后一部分效果图类似如下:

Pic

作者:冥河 QQ:3304576112
交流QQ群:554701039 C语言讲课群
本教程内容由本站保留版权,请勿复制传播
抖音
©2015-2024 惧留孙网 juliusun.com

京ICP备15039193号-1

首页 教程 下载 文章 聊天 我的