2

[转载]嗯,让我们彻底搞懂C/C++函数指针吧(三)

 2 years ago
source link: http://cedar-renjun.github.io/2015/12/28/C-and-C-plusplus-pointer-3/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

[转载]嗯,让我们彻底搞懂C/C++函数指针吧(三)

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://hipercomer.blog.51cto.com/4415661/792302

3.6 使用函数指针数组

函数指针有意思的地方在于,它使用从0到n-1这个n个连续的整数下标直接映射到函数上。
和前面一样,我们也是类比着定义普通指针数组来定义函数指针数组。首先,考虑一个浮点数指针数组,数组的长度为10.我们都知道用下面的形式来定义:

float * pFloatArray[10];

从形式上分析,用中括号明确了是定义指针变量还是定义指针数组这个语义。用数字10明确了这个数组能容纳多少个函数指针这个语义。形式上看,中括号是紧接在指针名称的后面再中括号里面是一个需要在编译时期间就能够确定的常数。
现在我们来类比函数指针数组的定义,定义一个指向函数指针类型为:float (*)(float,float)的函数指针数组,数组长度为10.正确的形式为:

float(* pFunctionArray[10])(float,float)

从形式上看,这种定义方式和定义普通指针的定义方式是一致的:都是在指针名称后面紧接着一个中括号,然后里面是一个编译期间能够确定的常数。这种形式上的一致性,可以方便我们对形式的记忆,进而达到对内容的理解。
下面是一个例子程序:


/*
* Author :Choas Lee
* Date :2012-02-28
*/

#include<stdio.h>

float add(float a,float b){return a+b;}

float minus(float a,float b){return a-b;}

float multiply(float a,float b){return a*b;}

float divide(float a,float b){return a/b;}

int main()

{

float(*func_pointers[4])(float,float)={add,minus,multiply,divide};

int i=0;

float a=10.0,b=5.0;

for(i=0;i<4;i++)

{

printf("result is %f\n",func_pointers[i](a,b));

}

return 0;

}

以下为对应的运行结果:

result is 15.000000 
result is 5.000000 
result is 50.000000 
result is 2.000000

3.7 使用typedef

从哲学角度讲,形式过于复杂的话,还是抽象的层次太低。如果我们使用多层次的抽象,这样最上层的表示就会简化很多。这就是引入typedef的原因,使用typedef可以简化函数指针的定义,因为typedef可以定义新的类型:
同样,在使用typedef定义函数指针类型的时候,也和普通的使用typedef引入新类型的方式不一样。我们和前面一样对照着普通的定义方式来学习:

typedef int bool;

这在C语言中很常用,由于C语言中没有bool类型,这样定义之后可以从形式上引入一个bool类型,提高代码可读性。所以形式为:

typedef 已知类型 新类型;

现在我们要将float ()(float,float)类型声明为一种新类型,按照上面的方式,貌似为:typedef float()(float,float) fpType;然而,前面的经验告诉我们应该这样定义啊:

typedef float(*fpType)(float,float);

这样我们就可以用fpType来表示float ()(float,float)这种类型了。所以定义一个新的指向float ()(float,float)类型的指针变量的时候,我们就可以采用下面这种形式了:

fpType pFunction;

在定义函数指针数组的时候可以这样定义:

fpType pFunctions[10];

在定义函数指针类型参数时可以这样定义:

void func(fpType pFunction);

在定义函数指针类型的返回值时可以这样定义:

fpType func(int a);

现在我们再来看一下,unix中的那个signal函数,其形式为:

void (*signal)(int signo,void (*func)(int)))(int);

现在我们定义一个类型为:

typedef void (*pSgnType)(int);

这样上面的函数就能表达为:

pSgnType signal(int signo,pSgnType func);

这样是不是看起来清爽多了。
其实上面的signal函数也能这样定义:
首先引入新类型:

typedef void SgnType(int)

然后signal函数的声明改为:

SgnType *signal(int signo,SgnType *func);

按照前面对这些形式的解释,理解这个应该没难度~~
现在在引入最后一个例子,关于使用typedef来简化函数指针定义的:

 
/*
* Author :Choas Lee
* Date :2012-02-29 00:25
*/

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

float add(float a,float b){return a+b;}
float minus(float a,float b){return a-b;}
float multiply(float a,float b){return a*b;}
float divide(float a,float b){return a/b;}

typedef float (*pArithmeticOperations)(float,float);
typedef float ArithmeticOperations(float,float);


int main()

{

pArithmeticOperations pao=add;
pArithmeticOperations paos[4]={add,minus,multiply,divide};

ArithmeticOperations *ao=add;
ArithmeticOperations *aos[4]={add,minus,multiply,divide};

float a=10.0,b=5.0;
float result=0.0;
int i=0;
result=pao(a,b);

printf("the result of pao is %f\n",result);
printf("the results of paos are:\n");

for(i=0;i<4;i++)
{

result=paos[i](a,b);
printf("result=%f\n",result);

}

result=ao(a,b);
printf("\n\nthe result of ao is :%f\n",result);
printf("the results of aos are:\n");

for(i=0;i<4;i++)
{
result=aos[i](a,b);
printf("result=%f\n",result);
}

return 0;

}

输出结果为:

result=15.000000 
result=5.000000 
result=50.000000 
result=2.000000 
the result of ao is :15.000000 
the results of aos are: 
result=15.000000 
result=5.000000 
result=50.000000 
result=2.000000

时间不早了,该回去睡觉了~

向作者Choas Lee 致谢,感谢您写了这么好的文章
By Cedar


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK