怎么理解(*(void(*)())0)();这条语句

《C陷阱和缺陷》书中所说,表达式(*(void(*)())0)()功能主要用于模拟在计算机启动时,作为硬件调用首地址为0的子程序的C语句,这段语句的含义是什么?下面是转载的一篇博客,在此发一下,并附上作者的链接以示尊敬。https://blog.csdn.net/yxfabcdefg/article/details/82928604

1、铺垫
在分析上面的语句前,我们先从简单的入手。先来区别和理解下面这两个定义。

float *g(); 和 float (*h) ();

直接上答案:由于( )结合的优先级别高于*,所以g先和后面的( )结合,构成一个函数,该函数的返回值是一个指向float 数的指针。同理,h是一个函数指针,它所指向的函数的返回值是一个浮点数。

当我们知道如何声明一个给定类型的变量,那么不难得出该类型的类型转换:只需要把声明中的变量名和声明末尾的分号去掉,然后将剩下的部分用一个括号整个“封装”起来。最简单的例子比方说我们以前学过的强制转换 (int) value这类的,但是我们现在稍微复杂一些。如下:

float (*h) (); 表示h是一个指向返回值为浮点类型的函数的指针,所以有

(float (*) () ) 表示一个“指向返回值为浮点类型的函数的指针”的类型转换 (这一步需要理解一下)

2、理解
有了上面的铺垫之后,我们就开始理解(*(void (*)())0)();这个语句。

1)(void (*)()) 里面的这个和铺垫的一样,是一个类型转换,表示一个“指向返回值为void类型的函数的指针”的类型转换。

  1. (void (*)()) 0这是表示将常数0转换为“指向返回值为void的函数指针”类型。

  2. 有了1) 和 2)的理解之后,我们就明白,0是一个函数指针,它指向的函数的返回值类型为void,这样就比较好办了,那我们就按照使用指针变量的方法去理解它。我们使用一个指针变量的时候,前面会带一个*号,同理,对于这样一个函数指针,我们在调用它的时候。也类似地这么调用,就是(*(void (*)())0)();这就分析完了。

3、补充
这个例子主要运用在计算机地址方面,比方说arm芯片一上电的时候,是从0地址处开始执行程序。而要对各个状态字进行配置或者存入某个内存块的时候,处理的方法也都是把一个常数(也就是这个地址)转换成一个指针类型,然后对这个指针进行操作就能对该地址进行操作,这方面在嵌入式的配置方面见得比较多。

之前有一个功能挺复杂的驱动程序,其中有一条语句是这样的:

pos == IOFPGA_DO_DATA_ADDR(iofpga_if_get_dod_addr(), pfifo) ;

那我就进去看一下它的定义咯,如下:

#define IOFPGA_DO_DATA_ADDR(base, reg)((unsigned int)&(((struct st_iofpga_do_data *)((int)base))->reg))

右边的表达式我一看就知道在干嘛了(因为在此之前我看过标题的例子),我们看一下右边的表达式对这base和reg这两个形参做了什么事情,很明显嘛:

1)首先把base强制转换为int类型,注意,它是一个常数。

2)结合上面的例子分析,(struct st_iofpga_do_data *)((int)base)和上面的例子用法一样,就是把一个常数转换成一个指针,这 里是转换成自定义的结构体指针。

3)((struct st_iofpga_do_data *)((int)base))->reg)把这个常数转换成结构体指针之后,在这个结构体中找到传入的reg成员。
4) &(((struct st_iofpga_do_data *)((int)base))->reg)) ` 找到该结构体里面的这个成员之后,用&取其地址

5) (unsigned int)&(((struct st_iofpga_do_data *)((int)base))->reg) &取到这个成员的地址之后,强制转换为(unsigned int)类型

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值