background image

  函数指针

  首先要理解以下三个问题:

  (1)语言中函数名直接对应于函数生成的指令代码在内存中的地
址,因此函数名可以直接赋给指向函数的指针;

  (2)调用函数实际上等同于"调转指令+参数传递处理+回归位置入栈",
本质上最核心的操作是将函数生成的目标代码的首地址赋给 CPU 的 PC 寄存
器;

  (3)因为函数调用的本质是跳转到某一个地址单元的 code 去执行,所
以可以"调用"

 

一个根本就不存在的函数实体,晕?请往下看:

  请拿出你可以获得的任何一本大学《微型计算机原理》教材,书中讲到,
186 CPU 启动后跳转至绝对地址 0xFFFF0(对应 C 语言指针是
0xF000FFF0,0xF000 为段地址,0xFFF0 为段内偏移)执行,请看下面的
代码:

typedef void (*lpFunction) ( ); /* 

 

定义一个无参数、无返回类型的 */

/* 

 

函数指针类型 */

lpFunction lpReset = (lpFunction)0xF000FFF0; /* 定义一个函数指

针,指向*/
/* CPU

 

启动后所执行第一条指令的位置 */

lpReset(); /* 

 

调用函数 */

  在以上的程序中,我们根本没有看到任何一个函数实体,但是我们却执
行了这样的函数调用:lpReset(),它实际上起到了"软重启"的作用,跳转到
CPU 启动后第一条要执行的指令的位置。

  记住:函数无它,唯指令集合耳;你可以调用一个没有函数体的函数,
本质上只是换一个地址开始执行指令!

  数组 vs.动态申请

  在嵌入式系统中动态内存申请存在比一般系统编程时更严格的要求,这
是因为嵌入式系统的内存空间往往是十分有限的,不经意的内存泄露会很快
导致系统的崩溃。

  所以

一定要保证你的 malloc 和 free 成对出现

,如果你写出这样的一段程序:

char * function(void)
{

 char *p;