OpenEdv-开源电子网

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

关于C语言函数指针的问题

[复制链接]

10

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
113
金钱
113
注册时间
2016-12-19
在线时间
30 小时
发表于 2017-4-8 11:13:30 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 HUSTPY 于 2017-4-8 11:14 编辑

这三个程序都是可以运行的(用VS2012编译),请问他们的区别在哪里呢?该如何理解

1  #include<stdio.h>
typedef void (*fun)(void);
void show(void)
{
        printf("I am show!\n");
}
void main()
{
        fun ptr;
        ptr=show;
        ptr();
}

2
#include<stdio.h>
typedef void (*fun)(void);
void show(void)
{
        printf("I am show!\n");
}
void main()
{
        fun ptr;
        ptr=&show;
        (*ptr)();
}

3
#include<stdio.h>
typedef void (*fun)(void);
void show(void)
{
        printf("I am show!\n");
}
void main()
{
        fun ptr;
        ptr=show;
        (*ptr)();
}



最佳答案

查看完整内容[请看2#楼]

按照&运算符本来的意义,它要求其操作数是一个对象,但函数名不是对象(函数是一个对象),本来&show是非法的,但很久以前有些编译器已经允许这样做, c/c++标准的制定者出于对象的概念已经有所发展的缘故,也承认了&show的合法性。 因此,对于show和&show你应该这样理解,test是函数的首地址,它的类型是void (),&show表示一个指向函数show这个对象的地址, 它的类型是void (*)(),因此show和&show所代表的地址值是一样的 ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
92
金钱
92
注册时间
2014-11-15
在线时间
9 小时
发表于 2017-4-8 11:13:31 | 显示全部楼层
按照&运算符本来的意义,它要求其操作数是一个对象,但函数名不是对象(函数是一个对象),本来&show是非法的,但很久以前有些编译器已经允许这样做,
c/c++标准的制定者出于对象的概念已经有所发展的缘故,也承认了&show的合法性。
因此,对于show和&show你应该这样理解,test是函数的首地址,它的类型是void (),&show表示一个指向函数show这个对象的地址,
它的类型是void (*)(),因此show和&show所代表的地址值是一样的,但类型不一样。show是一个函数,&show表达式的值是一个指针!
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2017-4-10 01:58:10 | 显示全部楼层
帮顶
回复

使用道具 举报

23

主题

256

帖子

0

精华

高级会员

Rank: 4

积分
767
金钱
767
注册时间
2017-2-19
在线时间
133 小时
发表于 2017-4-10 16:53:48 | 显示全部楼层
定义一个函数指针类型。
比如你有三个函数:
void hello(void) { printf("你好!"); }
void bye(void) { printf("再见!"); }
void ok(void) { printf("好的!"); }

typdef void (*funcptr)(void);
这样就构造了一个通用的函数
你用的时候可以这样:
void speak(int id)
{
   funcptr words[3] = {&hello, &bye, &ok};
   funcptr fun = words[id];
   (*fun)();
}

这样的话,如果speak(0)就会显示“你好!”
speak(1)就会显示“再见!”
speak(2)就会显示“好的!”

用于处理参数和返回值的形式都一样,但是功能不确定的一组函数,可以使用函数指针。

比如算术运算符,加、减、乘、除,都可以用typedef int (*calc)(int,int)代表,等等
回复

使用道具 举报

10

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
113
金钱
113
注册时间
2016-12-19
在线时间
30 小时
 楼主| 发表于 2017-4-10 23:44:43 | 显示全部楼层
刘东君 发表于 2017-4-10 16:53
定义一个函数指针类型。
比如你有三个函数:
void hello(void) { printf("你好!"); }

请看清楚问题,我的问题是:
ptr=show;ptr();或者ptr=&show;(*ptr)();或者 ptr=show;(*ptr)();
三个都可以运行。区别在哪
回复

使用道具 举报

60

主题

409

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2814
金钱
2814
注册时间
2012-10-17
在线时间
653 小时
发表于 2017-4-11 09:14:46 | 显示全部楼层
本帖最后由 civic7366 于 2017-4-11 09:30 编辑

1.函數名稱跟數組名稱本來就代表起始位址了,函數或數組名前面加不加&都是一樣的

2.ptr()跟(*ptr)()一樣,就不知道為啥了...這邊函數名稱好像對*沒反應 (******ptr)()一樣可以調用呢
回复

使用道具 举报

23

主题

256

帖子

0

精华

高级会员

Rank: 4

积分
767
金钱
767
注册时间
2017-2-19
在线时间
133 小时
发表于 2017-4-11 12:29:52 | 显示全部楼层
HUSTPY 发表于 2017-4-10 23:44
请看清楚问题,我的问题是:
ptr=show;ptr();或者ptr=&show;(*ptr)();或者 ptr=show;(*ptr)();
三个 ...

一个人名字的不同3种叫法。。。比如说:小明,明明。。。
回复

使用道具 举报

23

主题

256

帖子

0

精华

高级会员

Rank: 4

积分
767
金钱
767
注册时间
2017-2-19
在线时间
133 小时
发表于 2017-4-11 12:31:16 | 显示全部楼层
HUSTPY 发表于 2017-4-10 23:44
请看清楚问题,我的问题是:
ptr=show;ptr();或者ptr=&show;(*ptr)();或者 ptr=show;(*ptr)();
三个 ...

你先理解这一句,typedef void (*fun)(void);  再说下面的,
回复

使用道具 举报

23

主题

256

帖子

0

精华

高级会员

Rank: 4

积分
767
金钱
767
注册时间
2017-2-19
在线时间
133 小时
发表于 2017-4-11 13:55:10 | 显示全部楼层
第二个和第三个可以理解,第一个对吗??????????? 你换个编译器试下就知道了!!
回复

使用道具 举报

10

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
113
金钱
113
注册时间
2016-12-19
在线时间
30 小时
 楼主| 发表于 2017-4-11 16:04:35 | 显示全部楼层
刘东君 发表于 2017-4-11 13:55
第二个和第三个可以理解,第一个对吗??????????? 你换个编译器试下就知道了!!

哈哈,说了亲测可用。不论是VC6.0还是VS2012还是Free Online IDE,三个都是正确的
回复

使用道具 举报

10

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
113
金钱
113
注册时间
2016-12-19
在线时间
30 小时
 楼主| 发表于 2017-4-11 16:05:34 | 显示全部楼层
HUSTPY 发表于 2017-4-11 16:04
哈哈,说了亲测可用。不论是VC6.0还是VS2012还是Free Online IDE,三个都是正确的

或者说是可以执行的,也许编译器做了什么处理吧
回复

使用道具 举报

10

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
113
金钱
113
注册时间
2016-12-19
在线时间
30 小时
 楼主| 发表于 2017-4-11 16:12:36 | 显示全部楼层
刘东君 发表于 2017-4-11 13:55
第二个和第三个可以理解,第一个对吗??????????? 你换个编译器试下就知道了!!

讲真,函数名就是该函数的地址,把它的值赋给一个指向函数的指针是没问题的,相反ptr=&show反而有点不好理解。
回复

使用道具 举报

10

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
113
金钱
113
注册时间
2016-12-19
在线时间
30 小时
 楼主| 发表于 2017-4-11 16:15:02 | 显示全部楼层
civic7366 发表于 2017-4-11 09:14
1.函數名稱跟數組名稱本來就代表起始位址了,函數或數組名前面加不加&都是一樣的

2.ptr()跟(*ptr)()一樣, ...

对啊,神奇。一颗赛艇,(*****ptr)也可以编译通过诶
回复

使用道具 举报

10

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
113
金钱
113
注册时间
2016-12-19
在线时间
30 小时
 楼主| 发表于 2017-4-11 16:22:36 | 显示全部楼层
http://bbs.csdn.net/topics/310105530
这里有一篇帖子,说的有点意思

大意是

按照&运算符本来的意义,它要求其操作数是一个对象,但函数名不是对象(函数是一个对象),本来&test是非法的,但很久以前有些编译器已经允许这样做,c/c++标准的制定者出于对象的概念已经有所发展的缘故,也承认了&test的合法性。
回复

使用道具 举报

10

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
113
金钱
113
注册时间
2016-12-19
在线时间
30 小时
 楼主| 发表于 2017-4-11 16:25:11 | 显示全部楼层
HUSTPY 发表于 2017-4-11 16:22
http://bbs.csdn.net/topics/310105530
这里有一篇帖子,说的有点意思

只是没说 (*ptr);(*******ptr);估计也是被这样类似的处理了吧
回复

使用道具 举报

60

主题

409

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2814
金钱
2814
注册时间
2012-10-17
在线时间
653 小时
发表于 2017-4-11 17:07:01 | 显示全部楼层
所以不知道你(*ptr)(); 哪來看來的... 還是自己亂寫的?  

回复

使用道具 举报

23

主题

256

帖子

0

精华

高级会员

Rank: 4

积分
767
金钱
767
注册时间
2017-2-19
在线时间
133 小时
发表于 2017-4-12 11:32:18 | 显示全部楼层
HUSTPY 发表于 2017-4-11 16:25
只是没说 (*ptr);(*******ptr);估计也是被这样类似的处理了吧

(*ptr)() 这个是正确的。 看看下面这个图片,是谭浩强的C语言 微信图片_20170412113007.jpg 微信图片_20170412113014.jpg


回复

使用道具 举报

23

主题

256

帖子

0

精华

高级会员

Rank: 4

积分
767
金钱
767
注册时间
2017-2-19
在线时间
133 小时
发表于 2017-4-12 11:51:27 | 显示全部楼层
刘东君 发表于 2017-4-12 11:32
(*ptr)() 这个是正确的。 看看下面这个图片,是谭浩强的C语言


微信图片_20170412115021.jpg
回复

使用道具 举报

10

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
113
金钱
113
注册时间
2016-12-19
在线时间
30 小时
 楼主| 发表于 2017-4-12 12:30:29 | 显示全部楼层

是,这个也是最容易接受的
回复

使用道具 举报

60

主题

409

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2814
金钱
2814
注册时间
2012-10-17
在线时间
653 小时
发表于 2017-4-12 17:02:34 | 显示全部楼层
這本書不是被罵很慘的...在main裡面宣告函數....

而且工作4年了 沒看過有人用你所謂正確的方式調用

回复

使用道具 举报

0

主题

51

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
370
金钱
370
注册时间
2014-3-5
在线时间
65 小时
发表于 2017-4-19 20:36:46 | 显示全部楼层
本帖最后由 文刀言身寸 于 2017-4-19 20:43 编辑

~mark!
急不来总有障碍客观的存在...
回复

使用道具 举报

3

主题

73

帖子

0

精华

初级会员

Rank: 2

积分
196
金钱
196
注册时间
2017-5-4
在线时间
21 小时
发表于 2017-5-5 12:56:17 | 显示全部楼层
本帖最后由 mill 于 2017-5-5 12:58 编辑

我是这样理解的
&show和show是一样的,因为函数名就代表函数的入口地址,(*ptr)()和ptr是一样的,这时候PC指针应该就跳到了ptr所指向的地址处



回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-23 04:19

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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