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

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

[复制链接]
今日头条 提问时间: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管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版