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

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

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

时间: 2024-08-03 20:09:38

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

函数指针 c语言 指针-C语言指向函数的指针的调用

问题描述 C语言指向函数的指针的调用 int *d_bubblesort(int a[]int n)//数组长度为n的冒泡降序排序{int ij;int temp;for(i=0;i {for(j=n-1;j>i;j--){if(a[j]>a[j-1]){temp=a[j-1];a[j-1]=a[j];a[j]=temp;} }}return(a);} void main(){int i;int *p;int a[10]={65412398710};int (*fun)(intint);fun

C++中返回指向函数的指针示例_C 语言

在C++中,函数的形参可以是指向函数的指针,函数也可以返回函数的指针.例如:int (*ff(int)) (int *,int);表示:ff(int)是一个函数,带有一个int型的形参,该函数返回int (*) (int *,int),它是一个指向函数的指针,所指向的函数返回int型并带有两个分别是Int*和int型的形参.使用typedef可使得定义更加易懂:typedef int (*PF) (int *,int);PF ff(int);下面给出一个例子: 复制代码 代码如下: #inclu

C语言 函数指针(指向函数的指针)详解_C 语言

一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似.我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数.这种指针就是函数指针. 函数指针的定义形式为: returnType (*pointerName)(param list); returnType 为函数返回值类型,pointerNmae 为指针名称,param list 为函数参数列表.参数列表中

C++指向函数的指针实例解析_C 语言

通常来说C++函数指针是指指向函数的指针,而非指向对象的指针.就像其他指针一样,函数指针也指向某个特定的类型.函数类型由其返回类型以及形参表确定,而与函数名无关. 定义: char (*fP)(char,int); 赋值: char function(char i,int j) { } fp=function; 调用 (*fp)(10,100); type char (*FUN)(char,int);//类型定义 FUN fp ;//定义fp为指向函数的指针 volatile的用法和作用: co

2013-7-10学习笔记[字符串操作,指向函数的指针]

字符串处理函数1.strlen函数 这个函数可以用来测量字符串的字符个数,不包括\0 int size = strlen("mj"); // 长度为2     char s1[] = "lmj";  int size1 = strlen(s1); // 长度为3     char s2[] = {'m', 'j', '\0', 'l', 'm', 'j', '\0'};  int size2 = strlen(s2); // 长度为2    //在统计字符长度的时候

C++指向函数的指针用法详解_C 语言

本文以实例形式展示了C++指向函数的指针用法,是深入学习C++所必须掌握的关键知识点.分享给大家供大家参考之用.具体方法如下: 函数指针 现来看看以下声明语句,看看其含义: float (*h(int, void (*)(int)))(int); 以下是一个变量指针的定义语句: float* pf; 以下是一个普通函数的声明语句: float f(); 请看以下声明语句: float* g(); 因为()的优先级高于*, 所以相当于: float* (g()); g是一个函数, 返回值为floa

《C和C++代码精粹》——2.5 普通指针

2.5 普通指针 C和C++代码精粹 通常编写能接收指向任意类型参数的函数是很方便的.这是很有必要的,例如,用标准的库函数memcpy,能够从一个地址向另一个地址拷贝一块内存.你也可能想调用memcpy来拷贝自己创建的结构: struct mystruct a,b; /.../ memcpy(&a,&b,sizeof(struct mystruct)); 为了操作任意类型的指针,memcpy把它头两个参数声明为void型指针.可以不需要强制类型转换将任何类型的指针赋予void类型.也可以在

《C和C++代码精粹》——2.6 const指针

2.6 const指针 C和C++代码精粹注意memcpy函数第二个参数中的const关键字.这个关键字告诉编译器此函数将不会改变source指向的任何值(除了强制类型转换).当把指针作为参数传递时,总是合适地使用const限定符是一个很好的习惯,它不仅可以防止你无意中错误的赋值,而且还可以防止在作为参数将指针传递给函数时可能会修改了本不想改变的指针所指向的对象的值.例如,如果在程序清单2.6中的声明是: const int i=7,j=8; 有可能因为下面这条语句而得到警告: swap(&i,

《C和C++代码精粹》——第 2 章 指针2.1 容易出错的编程

第 2 章 指针 C和C++代码精粹本文仅用于学习和交流目的,不代表异步社区观点.非商业转载请注明作译者.出处,并保留本文的原始链接. 2.1 容易出错的编程 C和C++代码精粹"分割违规" "访问违规" "可疑的指针转换" "不可移植的指针转换" "空指针赋值" 这些消息听起来熟悉吗?指针出错是C++程序员必须应付的最令人厌恶的错误.实际上,长时间以来指针和它所提供给开发者的原始功能已经成为人们对C主要的