怎样返回另一个函数的地址
首先声明:文中的例子完全是按照本人的编程风格来编写的,所以,如果与你的编程风格不同,请原谅;再者,也许文中有些不对的地方,请给予指正。
在某些时候,我们需要一个函数返回另一个函数的地址,而非函数的返回值的时候,这是一个很有用的问题,因为某些时候,我们形参是需要一个函数的地址,需非一个函数值的时候,这时候就需要我们去寻找函数的地址,通常我们只关心函数的返回值,很少去关心函数的地址,但是,在上述的某些时候,关心函数的地址更加为重要。
其实,函数名本身就是函数的地址,它标志此函数在内存中的启始位置,只是我们通常调用函数的时候都只用其返回值,所以,对函数名这一标号的真实意义没有去过多的了解,关于函数名的一些问题,请读者去参考相关的资料。在此我来分析怎么从一个函数返回另一个函数地址。
首先,如果你的指针学得够好的话,应该会想到这样的一个问题,我可以返回一个指针,这个指针指向一个函数,不错,就个指针就是我通常所说的函数指针(并非指针函数,请注意这两个名词之间的区别),那么这样一分析不就出来了吗,一个返回函数指针的函数就能办到,这也是一般常用的办法,但是在函数声明与调用时就有些问题了,首先我们来分析一下声明,第一点我们必须保证它是一个函数,再次这个函数还返回一个指针,并且这个指针指向另一个函数,就这样就搞定了,在此假设读者对函数指针有一定的了解,这样就很好办事了,我们先来声明一个函数指针,例如 int (*fun)(int,int),这个声明就是一个函数指针,它表明fun是一个指针,它所指向的是一个int xx (int,int)的函数,如果读者你看过《C专家编程》,在3.3节中有一个关于声明的优先级规则的,那么效果会更好。好了,我接着分析一个我们的原问题,可以从函数指针开始出发,根据C语言中声明的优先级规则(请查看《C专家编程》),我们可以应用其后缀规则来变种我们所需的函数声明,真正的一种满足文章需求的声明为int (*fun(int)(int,int),这对于初学者有点难度,我们从C语言中声明的优先级规则开始,第一可以确定fun是一个有一个int形参的函数,该函数的返回值是一个指针,该指针指向一个int xx(int,int)的函数,好了,这样就把该函数的原形给确定下来了。下面我们应以这个函数原形为出发点,写一个简单的例子。完整的例子如下(说明,这个例子是本人在网上看到的一个公司的笔试题,这种解法有些烦锁,关于这个题目的解法我在《函数名之标号地址》一文中写出了三种解法,写这一篇文章所用的例子完全从其中获取一些源码):
#ifndef _TEST_C_
#define _TEST_C_
#include <stdio.h>
int _my_add(int,int);
int _my_sub(int,int);
int _my_mul(int,int);
int _my_div(int,int);
int _my_mod(int,int);
unsigned long function_buffer[][2] = {
(unsigned long) _my_add,'+',
(unsigned long) _my_sub,'-',
(unsigned long) _my_mul,'*',
(unsigned long) _my_div,'/',
(unsigned long) _my_mod,'%',
};
int (*_my_function(int))(int,int);
int main(void)
{
int number_one;
int number_two;
int number_control;
int (*temp_fun_pin)(int,int);
while(1)
{
printf("这是一个简单的计算器,主要有下面的功能!/n");
printf(" 1:加/n 2:减/n 3:乘/n 4:除/n 5:求模/n");
printf("请输入第一操作数 第二操作数 相关运算/n");
scanf("%d %d %d",&number_one,&number_two,&number_control);
if(((number_control == 4) && (!(number_two | 0x0)))/
|| (number_control > 5)){
printf("input is err/n");
continue;
}
temp_fun_pin = _my_function(number_control);
printf("/n%d %c %d = %d/n/n",number_one,/
*(*(function_buffer + number_control - 1) + 1),/
number_two,temp_fun_pin(number_one,number_two));
}
return 0;
}
int (*_my_function(int number_control))(int,int)
{
int (*temp_fun_pin)(int,int);
temp_fun_pin = /
(int (*)(int,int))function_buffer[number_control - 1][0];
return temp_fun_pin;
}
int _my_add(int number_one,int number_two)
{
return number_one + number_two;
}
int _my_sub(int number_one,int number_two)
{
return number_one - number_two;
}
int _my_mul(int number_one,int number_two)
{
return number_one * number_two;
}
int _my_div(int number_one,int number_two)
{
return number_one / number_two;
}
int _my_mod(int number_one,int number_two)
{
return number_one % number_two;
}
#endif
在上面的分析忘记了分析怎么调用些函数了,其实只要类型相匹配就可以了,函数的返回值是一个函数指针,那么我们就声明一个函数指针,让这个函数指针来获取函数的返回值就行了。
其实,上述方法有一点难于理解,这需要读者对指针有相当的了解,所以,我接着来实现一个更为简单一点的例子,这个例子需要读者知道函数名其实就是一个标号,标志其在内存中的地址,关于不同系列CPU地址所用的类型请参考相关的CPU手册,在此以unsigned long来做为内存地址的类型。这一个列子,只需要读者再有一点函数指针的基础,就能很容易地理解,完全比上一个例子更加好理解,完整代码如下:
#ifndef _TEST_C_
#define _TEST_C_
#include <stdio.h>
int _my_add(int,int);
unsigned long _my_call_function(void);
int main(void)
{
int number_one;
int number_two;
int result;
unsigned long my_fun_address;
while(1)
{
printf("这是一个应用函数地址进行调用函数的例子,主要用加法来验证/n");
printf("请输入被加数,加数/n");
scanf("%d %d",&number_one,&number_two);
my_fun_address = _my_call_function();
result = ((int (*) (int,int)) my_fun_address)(number_one,number_two);
printf("/n%d %c %d = %d/n/n",number_one,'+',number_two,result);
}
return 0;
}
unsigned long _my_call_function(void)
{
return (unsigned long)_my_add;
}
int _my_add(int number_one,int number_two)
{
return number_one + number_two;
}
#endif
此例子有点多做的问题,如果就这个例子来说,直接调用那不更好,但是这个例子的目的不在于怎么调用一个函数,需要说明的是怎么直接返回函数的地址并调用之。所以,看起来才有一点多余。
好了,本人的知识水平也只能写成这样了,如果有什么不对的地方,请给予指正,让本人也有学习与改正的机会。
舒稳
2010.8.4于长沙理工大学