OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9384|回复: 22

战舰STM32例程中的USMART中一条语句请教下!

[复制链接]

1

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
151
金钱
151
注册时间
2012-10-13
在线时间
50 小时
发表于 2012-12-15 17:55:32 | 显示全部楼层 |阅读模式
 在USMART例程中的void usmart_exe(void);这个函数中的 res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0]);这句语句有点不明白,
希望原子哥教我一下,这指针有点乱!我说下我的看法。
 
语句左边的res 变量的类型是u32的,这个变量是用来保存返回值的。
语句右边,要弄清楚它的结合性 ,结合应该是这样吧:(    *(   u32(*)()    )usmart_dev.funs[id].func    )(temp[0])  这里假设有一个参数,假如id=0;

有关的结构体:
 //函数名列表 
struct _m_usmart_nametab
{
 void* func;         //函数指针
 const u8* name;  //函数名(查找串) 
};

//usmart控制管理器
struct _m_usmart_dev
{
 struct _m_usmart_nametab *funs; //函数名指针
}

struct _m_usmart_nametab usmart_nametab[]=
{
       (void*)delay_ms,"void delay_ms(u16 nms)",
}



res=(    *(   u32(*)()    )usmart_dev.funs[id].func    )(temp[0]) ;          //这句不明白

usmart_dev.funs[id].func 是一个指针变量,但不指定它是指向哪一种类型数据的,假如usmart_dev.funs[0].func = (void*)delay_ms,(void*)delay_ms,delay_ms是函数的首地址,加一个(void *)是什么意思呢,u32(*)()是强制转换么?没看到过这种写法,u32是数据类型, u32(*)中的*用括号括起来,如果单这样,意思是指针指向U32类型的数据,
但是u32(*)后面再加个();变成u32(*)(),这里看不明白了?原子哥这是什么意思呢?  我现在的总理解是,指向一个函数,返回值的数据类型是U32型的。
我对这个语句中用到的u32(*)()不理解!请原子哥帮我讲解一下,谢谢!这个USMART我看了三天了,大部分都看懂了,现在就这里有点不明白,谢谢原子哥!

得之我幸,失只我命!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
151
金钱
151
注册时间
2012-10-13
在线时间
50 小时
 楼主| 发表于 2012-12-15 17:55:50 | 显示全部楼层
回复【楼主位】yihui184:
---------------------------------
顶一下!
得之我幸,失只我命!
回复 支持 反对

使用道具 举报

34

主题

805

帖子

4

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1865
金钱
1865
注册时间
2011-3-29
在线时间
140 小时
发表于 2012-12-15 19:44:54 | 显示全部楼层
res=(*(u32(*)())usmart_dev.funs[id].func)(temp[0]);
----
调用函数funs,实参为temp[0]。(*(u32(*)())部分为强制类型转换,转换为返回值为U32的函数指针,防止编译器错误提示。其中第一个*貌似可以不要,因为函数名==&函数名……太久没用这么复杂的玩意儿,说的可能不正确……具体你去看函数指针吧、指针数组吧……

void*为通用的指针类型,可以在不同的指针类型之间赋值转换而不产生警告信息。

u32(*)中的*用括号括起来-》应该是(*)()组合着看,表示函数指针。()里面是空的,实际是否应该加入形参类型?具体问版主吧。
业余程序玩家。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2012-12-15 20:22:23 | 显示全部楼层
这个是比较复杂,关键是(*(u32(*)()),这部分用来修饰usmart_dev.funs[id].func,其实就是个强制转换。usmart_dev.funs[id].func本身是一个void*的函数指针,通过(*(u32(*)()),将void*的函数指针强制转换为返回值是u32的函数指针然后参数不定。其实,还可以写成这样:
case 0://无参数(void类型)   
res=(*(u32(*)())usmart_dev.funs[id].func)();
break;
    case 1://有1个参数
res=(*(u32(*)(u32))usmart_dev.funs[id].func)(temp[0]);
break;
    case 2://有2个参数
res=(*(u32(*)(u32,u32))usmart_dev.funs[id].func)(temp[0],temp[1]);
break;
    case 3://有3个参数
res=(*(u32(*)(u32,u32,u32))usmart_dev.funs[id].func)(temp[0],temp[1],temp[2]);
这就确定了参数的个数,编译也是正常通过的。
这里我们进行简化,干脆就不指定参数个数,由后面的内容决定函数参数个数。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

1

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
151
金钱
151
注册时间
2012-10-13
在线时间
50 小时
 楼主| 发表于 2012-12-16 00:02:54 | 显示全部楼层
回复【4楼】正点原子:
---------------------------------
明白了,谢谢原子哥,我的理解是这样

//函数名列表  
struct _m_usmart_nametab
{
void* func; //函数指针
const u8* name; //函数名(查找串)  
};

//usmart控制管理器
struct _m_usmart_dev
{
      struct _m_usmart_nametab *funs; //函数名指针
}

//函数名列表初始化(用户自己添加)
//用户直接在这里输入要执行的函数名及其查找串
//假如如下::
struct _m_usmart_nametab usmart_nametab[]=
{    
       (void*)delay_ms,"void delay_ms(u16 nms)",    //(void *) 这里指返回值的类型为空
}

case 1://有1个参数 
res=(*(u32(*)(u32))usmart_dev.funs[id].func)(temp[0]); 

假如id=0;usmart_dev.funs[0].func=(void*)delay_ms    表示函数返回值为地址,数据类型为空,之前没看明白这里为什么加(void *)

因为我认为下面这个结构体的成员,void * func;   func这个指针变量,存放只有地址,加了(void *)我就纳闷了,原来,指针变量可以存放带有(void *),也就是可以存放,返回什么类型的地址,之前以为不可以。
struct _m_usmart_nametab
{
void* func; //函数指针
const u8* name; //函数名(查找串)  
};

理解了上面这点,就明白了u32(*)(u32)就是将( void*)强制转换为返回u32类型的地址,然后在u32(*)(u32)加上*还有(),变成
(*(u32(*)())就返回了u32类型的值。

正点原子哥,不知道我理解是否正确呢?

我还有点不明白就是
res=(*(u32(*)(u32))usmart_dev.funs[id].func)(temp[0]); 
这语句里面中,我们主要是实现强制类型转换,可不可以把参数的那个括号去掉呢,
变成res=(*(u32(*))usmart_dev.funs[id].func)(temp[0]); 
感觉加上有点怪!   
睡觉了,正点原子哥,呵呵!晚安!
得之我幸,失只我命!
回复 支持 反对

使用道具 举报

1

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
151
金钱
151
注册时间
2012-10-13
在线时间
50 小时
 楼主| 发表于 2012-12-16 00:04:04 | 显示全部楼层
回复【3楼】ofourme:
---------------------------------
谢谢,呵呵,明天再理清楚一下!
得之我幸,失只我命!
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2012-12-16 00:14:18 | 显示全部楼层
能不能去掉,你试试就知道了,呵呵.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

1

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
151
金钱
151
注册时间
2012-10-13
在线时间
50 小时
 楼主| 发表于 2012-12-16 09:13:20 | 显示全部楼层
回复【7楼】正点原子:
---------------------------------
恩,是的,我理解的对不对呀,正点原子哥,你还没回答我呀?
得之我幸,失只我命!
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2012-12-16 10:12:09 | 显示全部楼层
加上才是强制转换为函数指针,去掉,就不是了。
去掉你编译都不能通过呢!
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

21

主题

59

帖子

0

精华

初级会员

Rank: 2

积分
164
金钱
164
注册时间
2013-4-12
在线时间
0 小时
发表于 2013-10-23 09:28:49 | 显示全部楼层
回复【4楼】正点原子:
---------------------------------
u32(*)()     函数指针强制转换,(*(u32(*)())usmart_dev.funs[id].func)不是取内容吗?
自由的代价永远是警惕!
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2013-10-23 10:02:27 | 显示全部楼层
回复【10楼】西北风:
---------------------------------
不是读取内容,res是函数的返回值。这里是执行函数,然后返回值返回给res。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

21

主题

59

帖子

0

精华

初级会员

Rank: 2

积分
164
金钱
164
注册时间
2013-4-12
在线时间
0 小时
发表于 2013-10-23 11:04:20 | 显示全部楼层
回复【11楼】正点原子:
---------------------------------
意思是(*(u32(*)())usmart_dev.funs[id].func)中最前面的*是要求执行函数,是吗?
自由的代价永远是警惕!
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2013-10-23 14:21:44 | 显示全部楼层
回复【12楼】西北风:
---------------------------------
不是
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

18

主题

83

帖子

0

精华

初级会员

Rank: 2

积分
175
金钱
175
注册时间
2013-10-17
在线时间
0 小时
发表于 2013-12-2 01:12:42 | 显示全部楼层
回复【13楼】正点原子:
---------------------------------
原子哥好啊:
   第一个*是什么作用啊,我把它去掉了好像也可以的。。。不知道为什么啊。。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2013-12-2 13:00:45 | 显示全部楼层
回复【14楼】summerxiehao:
--------------------------------
哪一个?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

18

主题

83

帖子

0

精华

初级会员

Rank: 2

积分
175
金钱
175
注册时间
2013-10-17
在线时间
0 小时
发表于 2013-12-2 22:49:17 | 显示全部楼层
回复【15楼】正点原子:
---------------------------------
谢谢原子哥的回复,我已经知道答案了,呵呵
回复 支持 反对

使用道具 举报

13

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
136
金钱
136
注册时间
2012-8-28
在线时间
11 小时
发表于 2014-12-8 16:46:18 | 显示全部楼层
原子大哥
      楼上那位说的是第一个*去掉,变成这样
case 0://无参数(void类型)  
res=((u32(*)())usmart_dev.funs[id].func)();
break;  //
   case 1://有1个参数
res=((u32(*)())usmart_dev.funs[id].func)(temp[0]);
break;
......一次类推。
编译下载后发现也可以。测试了几个命令和函数发现也可以。能详细讲讲第一个*号的作用吗。我也感觉这个*加在这有点怪怪的味道。

回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2015-2-6
在线时间
0 小时
发表于 2015-2-14 12:21:28 | 显示全部楼层
回复【17楼】guotaosheng:
---------------------------------
二楼有说
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2015-7-3
在线时间
0 小时
发表于 2015-7-3 14:16:01 | 显示全部楼层
受益匪浅啊!就是因为强制转换少写了参数,蒙了一上午。
回复 支持 反对

使用道具 举报

7

主题

60

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
299
金钱
299
注册时间
2015-10-21
在线时间
52 小时
发表于 2016-2-19 10:23:01 | 显示全部楼层
今天阅读《C/C++程序员面试指南》中指针一块,以前一知半解的指针问题顷刻间懂了。

下面,可以做个测试,如果下面的指针问题你能够全都解答正确,那么你的C语言功底真是神一般的了。

1.int *p;

2.int **p;

3.int *p[10];

4.int (*p)[10];

5.int *p(int);

6.int (*p)(int);

7.int (*p[10])(int);

这七个难度还不是很大,相信大多数读者都能够答的出来。

答案:

1.一个指向整型数据的指针

2.一个指针的指针,它指向的指针指向一个整型数据

3.一个有十个指针的数组,该指针指向整型数据

4.一个指向有十个整型数据数组的指针

5.就一个函数(不是函数指针),该函数有一个整型参数,返回值为一个指向整型的指针

6.一个函数指针,该函数有一个整型的参数,返回值为整型类型

7.一个有十个指针的数组,该数组中的指针指向一个函数,该函数有一个整型参数并返回一个整型数

啊,当时看完我就吁了口气,真神一般似的,但是但我接着看下去,下面有碰到一个,我彻底崩溃了.......



题目是这样的:

请解析 (*(void (*)())0)() 的含义。// 怎么样?要HOLD住阿!

分析问题:

不卖关子了,但是我早HOLD不住了。书中的答案是这样的,

有些微处理器从0地址启动,有时为了模拟开机时的情形,需要设计一条C 语句,去执行0地址的内容,于是就有了(*(void (*)())0)() 这条语句。

这条语句一眼看上去让人头疼,但分析之后还是挺简单的。

首先,当有如下函数声明时:

void fun(param);

这个函数的调用形式为:fun(param);

题目的函数没有参数,所以就简化成fun();

而0是这个函数的入口地址,即0就是这个函数的指针值,指针的函数声明为:

void (*pFun)(param);

调用形式为:(*pFun)(param);

对于本题可以写成:( *0 ) ();

但是函数指针变量不能是个常数,所以还要把0强制转换成函数指针,根据原题可以元函数的函数指针原型为 void (*)();

于是(*(void (*)())0)()可以这样来分析,首先用void (*)()把0强制转换成了函数指针,然后再调用函数指针0所指向的函数。

可以用typedef来加深对本句的理解,如下:

typedef void (*pFun)();

((*pFun)0)();

这两句和(*(void (*)())0)()是等价的,但是这样更有助于加深对本句的理解。

总结:(*(void (*)())0)()就是 *(void (*)())0 所对应的函数的调用。



神一般的C语言指针.....希望对大家掌握指针有所帮助(*^__^*)

转自:http://www.cnblogs.com/xufeiyang/archive/2011/11/05/2237070.html
回复 支持 反对

使用道具 举报

0

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
151
金钱
151
注册时间
2016-1-4
在线时间
31 小时
发表于 2016-3-4 18:38:44 | 显示全部楼层
guotaosheng 发表于 2014-12-8 16:46
原子大哥
      楼上那位说的是第一个*去掉,变成这样
case 0://无参数(void类型)                                                         ...

http://blog.csdn.net/oscar999/article/details/8986088
回复 支持 反对

使用道具 举报

4

主题

59

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
367
金钱
367
注册时间
2016-8-29
在线时间
128 小时
发表于 2018-7-20 00:36:54 | 显示全部楼层
mark
回复 支持 反对

使用道具 举报

1

主题

36

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
350
金钱
350
注册时间
2016-7-29
在线时间
71 小时
发表于 2025-5-14 10:14:38 | 显示全部楼层
ofourme 发表于 2012-12-15 19:44
res=(*(u32(*)())usmart_dev.funs.func)(temp[0]);
----
调用函数funs,实参为temp[0]。(*(u32(*)())部分为 ...

感谢ofourme大神解惑,第一个*确实可以不要
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-7 19:57

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表