你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

有一个回调的看不太懂其意义,大家来讨论一下

[复制链接]
今日头条 提问时间:2016-6-2 11:31 /
大家好,

C文件里定义了一个
typedef void (*start_fn_t)(const sysparam_t *param);

另外,结构体的定义:
typedef struct {
    const char * bootver;
    uint32_t master_addr;
    uint32_t config_addr;
    const rsa_pub_key_t * key;
}sysparam_t;
extern const sysparam_t * sysparam;



最后,在一个函数里这样调用了一下
    ((start_fn_t)(*(uint32_t *)  (sysparam->master_addr + 4)))(sysparam);





这句话是函数的最后一句话,这句话看不懂啊。。貌似就是把一个地址强转成一个函数,然后带了个自己的参数,可是没有函数体啊。。函数使用typedef来定义的












收藏 评论3 发布时间:2016-6-2 11:31

举报

3个回答
潇潇雨歇pku 回答时间:2016-6-2 14:55:13
mark 学习
任风吹吹 回答时间:2016-6-2 16:46:22
1 首先 extern const sysparam_t * sysparam; 表示外部已经存在了这个一个sysparam_t *数据结构的常量指针,指向的内容是固定的,且是外部已经存在的。

2
(uint32_t *)  (sysparam->master_addr + 4)
取常量指针sysparam指向内容的数据成员master_addr再偏移4,master_addr的定义是uint32_t类型的整数,但是,很显然,sysparam->master_addr成员内存放的数据是个地址值,或者为一个指针值。因此将其强制转化为(uint32_t *)

3 接下来取出这个指针指向的数据内容。
*(uint32_t *)  (sysparam->master_addr + 4)
也就是说,sysparam的成员master_addr保存的数据是另一片内存的起始地址(这里暂时叫内存B)。这里只是取出这个另一片内存起始地址偏移4个字节的内容。

4 内存B中保存的是函数指针,类型为start_fn_t
因此,再次需要将内存B中的数据强制转化为start_fn_t类型才可以当做函数体来用
这个 ((start_fn_t)(*(uint32_t *)  (sysparam->master_addr + 4)))()就是强制转化为start_fn_t类型的函数体。
而 ((start_fn_t)(*(uint32_t *)  (sysparam->master_addr + 4)))(sysparam); 就相当于Fn(x);这样的函数调用了。

你滴,明白聊?

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2 神马都是浮云

查看全部评分

moyanming2013 回答时间:2016-6-2 17:36:39
本帖最后由 moyanming2013 于 2016-6-2 19:43 编辑
任风吹吹 发表于 2016-6-2 16:46
1 首先 extern const sysparam_t * sysparam; 表示外部已经存在了这个一个sysparam_t *数据结构的常量指针 ...

我补充一下:
1.对于
((start_fn_t)(*(uint32_t *)  (sysparam->master_addr + 4)))(sysparam);
理解起来从内到外,但上面的定义略显臃肿,建议这么使用:
(*(start_fn_t*)(sysparam->master_addr+4))(sysparam);
就直接执行函数了。
2.函数到底在哪?
函数在(sysparam->master_addr+4),其实sysparam->master_addr本身就是一个函数的地址(或者不是?!)那为什么还要再加4呢?
2.1.对于sysparam->master_addr如果不是函数地址,那他在一个函数地址的前面4字节处,这种情况下,sysparam->master_addr是一个结构体成员,这个成员下一个就是函数指针了。
2.2.对于sysparam->master_addr是函数地址,再加4就到函数体里面了,当然就执行不了函数。此时只有Cortex-M中的异常向量具有这个潜质,就是跳到下一个异常函数。
2.3.楼主是不是笔误?对于(sysparam->master_addr+4)其实应该是((int)(&sysparam->master_addr)+4),这样就是在调用sysparam的config_addr成员,显然config_addr也是个函数指针。建议楼主检查下程序,是否应该如此?!
对于((int)(&sysparam->master_addr)+4),显示转换为int是必要的。否则,对于(&sysparam->master_addr)这是个int型指针,对int型指针加4相当于加了4*sizeof(int*),也就是加了0x10,显然加0x10不是我们要的。所以先把(&sysparam->master_addr)转换为int型数,再对这个数加4,此时就是sysparam_t中的config_addr成员了。
综合看这个问题,楼主除了要看明白语句的意思,还要明白程序到底要干什么,我估计程序是要对config_addr成员进行调用,但是没写对,正确的如下:
(*(start_fn_t*)((int)(&sysparam->master_addr)+4))(sysparam);


所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版