C语言-语法陷阱(一)理解函数声明

it2024-07-01  42

理解函数声明

设计内容

设计一个程序,当计算机启动的时候,硬件将调用首地址为0位置的子例程。 经过思考,获得

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

先暂不看下列内容,思考一下,这个语句,到底实现了什么功能?

预备知识

变量与函数的声明

C语言中,有以下的特点(规则)。

任何一个变量在使用前均需要声明。 int i = 0; //声明一个有符号整形变量 i ,并赋初始值为0 u8 buf[64]; //声明一个无符号8bit的数组 buf,长度为64,这种经常使用在单片机开发中 任何一个函数,在使用的时候,均需要对其进行声明。 void fun1(void); //声明一个函数fun1,没有输入的参数,没有返回的参数 u8 fun2(u8 para1); //声明一个函数fun2,输入参数为u8 para1,返回参数类型为u8

C语言也可以用指针来指向一个变量或者一个函数。

指向变量的指针 //ptr为指向整形变量的指针 int i = 0; int *ptr = &i; //注意,在上述表达中,偶尔会有误认为 *ptr = &i ,但实际上,上述语句等同于下述语句 int i = 0; int *ptr; ptr = &i; 指向函数的指针 void (*fun1_ptr)(void); //fun1_ptr是指向一个函数的指针,这个函数没有返回值 int (*fun2_ptr)(void); //fun2_ptr是指向一个函数的指针,这个指针返回值为整形变量 //此处为什么要将*fun2_ptr,用括号括起来?思考“声明一个函数,其返回值为一个整型变量的指针。” 返回值为整形的指针 int *fun1(void); /* 由于()优先级高于*,所以 int (*fun2_ptr)(void);指的是fun2_ptr这个指针指向的函数,返回值为一个int变量; int *fun1(void);指的是fun1这个函数,返回值为一个指向int的指针。 注意区分两者的不同。 */

强制类型转换

u8变量强制转换成int u8 i = 1; (int)i; 指针可以强制类型转换吗? 可以。 int i = 1; int *int_ptr = &i; //此处将指针类型强制转换成u8 u8 *u8_ptr = (u8*)int_ptr; 指针可以强制类型转换,那么指向函数的指针可以吗? 可以 int (*fun1_ptr)(void); int fun1(void); fun1_ptr = fun1; //我希望将上述“指向返回值为整形的函数的指针”强制转换成“指向返回值为u8的函数的指针” u8 (*fun2_ptr)(void); int fun2(void); fun2_ptr = (u8 (*)(void))fun2;

如何调用一个函数指针所指向的函数?

int (*fun1_ptr)(void); int fun1(void); fun1_ptr = fun1; (*fun1_ptr)(); //调用fun1_ptr指向的函数,即fun1

回顾上述题目

有了上述的准备工作,我们做的是“设计一个程序,当计算机启动的时候,硬件将调用首地址为0位置的子例程。”

暂时可以做到的是,运行某个地址的函数。

int (*fun_ptr)(void); (*0)();

但这种做法是不行的,因为*需要一个指针来做操作数,并且这个指针为函数指针。

换句话说,我们只要将 0 强制转换成函数指针就可以了?

那么如何转换呢? 借用上述准备知识中的,函数指针强制类型转换,将常数0转换为“指向返回值为void的函数的指针类型”

(void (*)())0

然后将这一串东西,替换原本的0,即

int (*fun_ptr)(void); (*(void (*)())0)();

思考

如果用这种做法,能否正常运行?

int (*fun_ptr)(void); fun_ptr = 0; (*fun_ptr)();

个人看法:在C语言中,指针是不能随便赋值后访问的,我们不可以这样做。但未经实验验证过,期待各位的想法。

最新回复(0)