C代码实现程序的跳转|函数指针

嵌入式技术

1368人已加入

描述

文章开始前先抛出一个经典的面试题:

 

  凡是学过C语言函数的应该都知道,函数名其实就是个地址,是函数的入口地址。如果用 %p 来输出函数名,确实可以得到一个合法的地址。

#include 


int function(int a, int b)
{
    printf("this is test ...
");
}


int main()
{
    printf("%p
", function);


    return 0;
}

 

运行结果:

 

root@Turbo:test# ./test 
0x55a061ec3169

 

指针是用来保存地址的,那能不能把函数名直接赋值给指针呢?这个操作是可以的,这种指针我们把它称作函数指针。字符指针是char *,整型指针是int *,那函数指针应该怎么写?

 

假设有这么一个函数,返回值是整型,参数有两个。

 

int function(int a, int b)
{
    printf("this is test ...
");
}

 

如果要定义指针保存该函数的地址,应该写成这样。

 

int (*pFunction)(int, int);

 

其实分析起来也不难,用我之前给大家讲的右左法则。

先找到变量名 pFunction,向右看,是个右括号,再向左看,是个星号,于是得出结论,pFunction是个指针。然后再向右看,又是括号,C语言中括号除了表示优先级,剩下的就是函数会使用,所以指针指向函数。继续分析,函数有两个参数,函数的返回值是int。

既然是定义变量,就可以直接在后面初始化变量。

 

int (*pFunction)(int, int) = function;

 

于是指针 pFunction 就指向了函数function。调用函数的时候,不仅可以通过函数名调用,也能通过函数指针调用。

 

function(1, 2);
pFunction(1, 2);

 

注意:有个小问题,通过函数指针调用函数的时候,指针前面可以加星号,也可以不加星号,编译器都能通过,运行结果也一样。至于说哪种更合适,一直备受争论。

 

(*pFunction)(1, 2);

 

如果代码里面用到函数指针的地方太多,每次定义就显得比较麻烦。

 

int (*pFunction1)(int, int) = function;
int (*pFunction2)(int, int) = function;
int (*pFunction3)(int, int) = function;

 

如果是同一个类型的函数指针,我们完全可以使用 typedef 关键字来简化它.

 

typedef int (*T)(int, int);

 

写成这样,看起来非常的不顺眼,但是语法是没有问题的,意思就是用T来表示这种函数指针类型。接下来再定义变量的时候,可以直接写成:

 

T pFunction1 = function;
T pFunction2 = function;
T pFunction3 = function;

 

那么pFunction1的含义跟pFunction是一样的,都是函数指针。

最后,再回到文章开头的面试题。

如果是汇编语言,想要实现跳转直接就是一条指令。但是C语言中能跳转的语句不多,我能想到的就是调用函数以及goto语句。goto语句是通过标签来跳转,标签可操作空间不大,可以直接放弃。

剩下的就是函数。只要把给定的地址强转成函数指针,通过调用函数的形式,就能跳转到指定地址运行。

 

void (*p)(void) = 0x1000;
p();

 

不过这样写编译器会提示警告,编译器不允许直接把整数赋值给指针。需要加上强制类型转换。

 

void (*p)(void) = (void (*)(void))0x1000;
p();

 

可以简写成:

 

(void(*)(void))0x1000();

 

或者:

 

(*((void(*)(void))0x1000))();

 

 

  审核编辑:汤梓红
 
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分