《C和C++代码精粹》——2.12 指向函数的指针

简介:

本节书摘来自异步社区出版社《C和C++代码精粹》一书中的第2章,第2.12节,作者: 【美】Chuck Allison,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.12 指向函数的指针

C和C++代码精粹
一个指针可以指向函数也可以指向存储的对象。下面的语句声明fp是一个指向返回值为整型(int)的函数的指针:

int(*fp)( );

*ftp的圆括号是必需的,没有它的语句

int *fp( );

将fp声明为一个返回指向整型(int)指针的函数。这就是将星号与类型声明紧密相连的方式成为逐渐受人们欢迎的方式的原因之一。

int* fp();    //方式说明fp()返回一个指向整型的指针(int * )

当然,这种方式建议你通常应该每条语句只声明一个实体,否则,以下的语句将会使人感到迷惑:

int *ip, jp;  //jp不是一个指针!

如果想具体说明fp指向的函数就必须带有一定的参数,如果是一个浮点型(float)和一个字符串型,那么可以这样写:

int  (*fp) (float, char * );

然后可以在fp中存储这样一个函数的地址:

extern int g(float,char*);
fp=g;

表达式中函数的名字解析地址可以认为是指向那个函数代码区的开始的地址。下面的“hello,world”程序说明如何通过指针来执行一个函数。

/*hello.c: 通过函数的指针来说hello */
#include <stdio.h>
main()
{
   void ( * fp )( )=printf;
   fp("hello, world\n");
}

要通过指针来执行一个函数,你可能认为得这样写:

(*fp)("hello world\n");

来复引用指针。事实上,在ANSI C出现以前必须这样做,但是ANSI C 委员会决定容许像我在hello.c中那样使用的普通函数调用句法。由于编译器知道它是一个指向函数的指针,并且它还知道在该环境下所能做的惟一的一件事就是调用函数,因此这里没有任何模糊不清的表达。

当把函数名作为一个参数传递给另一个函数时,编译器实际上给这个函数传递了一个指针(与数组名类似)。但是你为什么曾经想过给另一个函数传递函数指针呢?C标准库中的排序函数qsort 的使用就是一个例子,采用简单和复合的排序关键字,它可以对由任何类型的元素所组成的数组排序。程序清单2.17中的程序说明怎样排序命令行参数字符串,在这种情况下所需要做的全部事情就是传递给qsort一个知道如何比较字符串的函数。一个函数(像qsort)通过由运行时决定的指针来调用另一个函数(像 comp)的行为叫做返调(callback)。

函数指针的数组在菜单驱动应用程序中很容易见到,假设想将以下的目录展现给用户:

1.返回

2.插入

3.更新

4.退出

程序清单2.18的程序直接把键盘输入作为索引放到指向处理每一个菜单选择函数的指针的数组中。

程序清单2.17 用qsort函数将命令行参数排序

// sortargs.cpp:  排序命令行参数  
#include <iostream>  
#include <cstring>  
#include <cstdlib>  
using namespace std;  

int comp(const void*, const void*);  

main(int argc, char *argv[])  
{  
    qsort(argv+1, argc-1, sizeof argv[0], comp);  
    while (--argc)  
        cout << *++argv << endl;  
}  

int comp(const void* p1, const void* p2)  
{  
    const char *ps1 = * (const char**) p1;  
    const char *ps2 = * (char**) p2;  
    return strcmp(ps1,ps2);  
}  

//从"sortargs *.cpp"命令输出:  
address.cpp  
arith.cpp  
array1.cpp  
array2.cpp  
array3.cpp  
array4.cpp  
array5.cpp  
array6.cpp  
array7.cpp  
array8.cpp  
array9.cpp  
bit1.cpp  
bit2.cpp  
convert.cpp  
inspect.cpp  
pointer.cpp  
ptr2ptr.cpp  
sortargs.cpp  
swap1.cpp  
swap2.cpp

程序清单2.18 用函数指针数组来处理菜单选择

/* menu.c:  举例说明函数数组*/  
#include <stdio.h>  

/*你一定要给这些提供定义*/  
extern void retrieve(void);  
extern void insert(void);  
extern void update(void);  
extern int show_menu(void);        /*返回keypress */  

main()
{  
  int choice;  
  void (*farray[])(void) = {retrieve,insert,update};  

  for (;;)  
    {  
        choice = show_menu();  
        if (choice >= 1 && choice <= 3)  
            farray[choice-1]();         /* 进程的需要 */  
        else if (choice == 4)  
            break;  
    }  
    return 0;  
}

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

相关文章
|
3天前
|
C++ 数据格式
LabVIEW传递接收C/C++DLL指针
LabVIEW传递接收C/C++DLL指针
10 1
|
1天前
|
C++ 编译器
数组指针、函数指针、指针数组、函数 指针数组、指针函数详细总结
数组指针、函数指针、指针数组、函数 指针数组、指针函数详细总结
|
3天前
|
存储 安全 程序员
C++:智能指针
C++:智能指针
19 5
|
4天前
|
自然语言处理 编译器 C语言
【C++】C++ 入门 — 命名空间,输入输出,函数新特性
本文章是我对C++学习的开始,很荣幸与大家一同进步。 首先我先介绍一下C++,C++是上个世纪为了解决软件危机所创立 的一项面向对象的编程语言(OOP思想)。
30 1
【C++】C++ 入门 — 命名空间,输入输出,函数新特性
|
4天前
|
存储 安全 C++
深入理解C++中的指针与引用
深入理解C++中的指针与引用
7 0
|
5天前
|
存储 安全 算法
【Linux | C++ 】基于环形队列的多生产者多消费者模型(Linux系统下C++ 代码模拟实现)
【Linux | C++ 】基于环形队列的多生产者多消费者模型(Linux系统下C++ 代码模拟实现)
22 0
|
5天前
|
算法 C++
【C++入门到精通】智能指针 shared_ptr循环引用 | weak_ptr 简介及C++模拟实现 [ C++入门 ]
【C++入门到精通】智能指针 shared_ptr循环引用 | weak_ptr 简介及C++模拟实现 [ C++入门 ]
10 0
|
5天前
|
安全 算法 数据安全/隐私保护
【C++入门到精通】智能指针 shared_ptr 简介及C++模拟实现 [ C++入门 ]
【C++入门到精通】智能指针 shared_ptr 简介及C++模拟实现 [ C++入门 ]
10 0
|
5天前
|
存储 算法 安全
【C++入门到精通】智能指针 auto_ptr、unique_ptr简介及C++模拟实现 [ C++入门 ]
【C++入门到精通】智能指针 auto_ptr、unique_ptr简介及C++模拟实现 [ C++入门 ]
11 0

热门文章

最新文章