函数指针的定义
首先看指针的定义,指针是指向某个变量的地址,实际不占用内存空间,就是个地址。例如:
int *p; //p指向某个int变量
int a=123;//int类型的变量a值为1,地址为编译器自动分配。
p=&a; //p指向变量a,p为变量a的地址
//此时,假设a的地址是0x1000,那么*p=123,p=0x1000。
在说函数指针定义之前,我们再引申一下,也是我以前从来没想过的。
变量a的名字其实对于MCU没有意义,没有地方保存a的名字‘a’,a这是对于我们(开发者)来说的一个好记的代号,在MCU中的表现就是,地址0x1000中存放数据123。那么就可以通过下面的方法直接对该地址进行赋值,而不通过变量a这个名字。
(int *)0x1000=123;
虚拟的p还是个指向int的指针,p指向的地址还是0x1000,只不过这个过程中没有指针p这个名字了,也没有变量a这个代号了。
这条语句正确解读应该是首先将0x1000强制类型转换为指针,然后对其赋值。
实测发现,应该调用如下
*(int *)0x1000=123;
并且这是一条语句,并不是声明或定义,也就是0x1000地址里事先并没有存放123,而是执行这一条语句后才赋值。program flash中会同时保存0x1000和123。
再来看函数指针,顾名思义,就是指向函数的指针,和普通指针一样,函数也是有类型的,有/无返回值,有无参数。先来看比较简单的无返回值值无参数的情况。
定义一个函数指针pfun:
void fun()
{
printf("123\n");
}
void(*pfun)() = &fun; //定义无返回值无参数的函数指针pfun,指向fun函数的入口地址;
(*pfun)(); //调用该函数指针,其值为指向函数fun的入口地址;
或者如下也是一样的效果:
void(*pfun)()=fun; //定义函数指针pfun,指向fun函数
pfun(); //调用该函数指针,即fun的入口地址
最终要达到调用fun()的效果就必须索引到fun()函数的入口地址。
再下一步,实现让程序跳转到绝对地址0x100000去执行。可以这样想,如果有一个函数,该函数的入口地址是0x100000,那么就可以通过调用该函数来实现跳转。但是事实上没有这个函数,于是就可以定义一个函数指针void(*fun)();
将该指针指向地址0x10000,即强制类型转换:
(void(*)())0x10000;
现在上式就是一个指向0x10000地址的函数指针,或者这样解释更好理解,这是一个函数指针,指向一个虚拟的函数fun,fun函数的入口地址为0x10000
再下一步就是调用这个函数指针指向的函数
(*((void(*)())0x10000))();
需要理解的关键点是,一是函数指针的定义和使用方法,二是函数名本身就是一个入口地址,例如通过uint16 i = (uint16)main语句就可以把main函数的入口地址赋值给i(实测有效)。
实测发现
i=(uint16)main和i=(uint16)(&main)都是取main的首地址;
(((void()())0x40000))();和(((void(*)())0x40000))();都可以实现程序跳转;
但是所有方式在main()中都无法实现跳转或软件复位,均是在boot程序中可以实现,尚无找到原因,猜测和中断开启有关。
https://blog.csdn.net/judyge/article/details/49824889
int main(void)
{
void (* my_function)(void);
//int *my_address = 0x8000;
my_function = (void (*)()) (0x8000);
my_function();
}
//
typdef void (*pStartType)(void);
pStartType pStart;
{
...
pStart = (pStartType)(0x40000);
pStart();
...
}
上面两种方式是相同的效果,在另一篇笔记里会重点谈一下typedef和函数指针的应用。
Update:
在DevC++里测试了一下四种通过函数指针调用函数的方式,都是可以的。如下:
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
void fun()
{
printf("我调用成功了\n");
}
int main()
{
printf("%s","test1");
void(*pfun)() = fun;
pfun();
printf("%s","test2");
pfun = fun;
(*pfun)();
printf("%s","test3");
pfun = &fun;
pfun();
printf("%s","test4");
pfun = &fun;
(*pfun)();
system("pause");
return 0;
}