OpenEdv-开源电子网

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

静态函数函数调用

[复制链接]

24

主题

208

帖子

0

精华

高级会员

Rank: 4

积分
714
金钱
714
注册时间
2014-4-8
在线时间
160 小时
发表于 2016-4-20 14:46:14 | 显示全部楼层 |阅读模式
1金钱
首先  在led.h中定义
typedef struct
{
  void (*plf_test_led) (void);
}
LED_TypeDef;

然后在led.c中定义
LED_TypeDef LED_VOP=
{
    test_led
};
然后在led.c中写了一个函数
static void test_led(void)
这是一个静态的函数

然后在main.c中写
LED_VOP.plf_test_led();

然后就调用了上面的那个静态函数,没有问题。
但是完全不明白为什么要这样写函数……

最佳答案

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

我的理解是,用static修饰的函数仅本文件可见,即其他函数调用test_led()也不会调用到你static修饰的这个函数。 那这个函数如何给外部使用呢,只能靠指针传递了。这个和static修饰的全局变量用法一样:无法通过变量名找到该变量,但可以通过指针访问。其他文件还可以命名相同的变量名且不会冲突。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
发表于 2016-4-20 14:46:15 | 显示全部楼层
我的理解是,用static修饰的函数仅本文件可见,即其他函数调用test_led()也不会调用到你static修饰的这个函数。
那这个函数如何给外部使用呢,只能靠指针传递了。这个和static修饰的全局变量用法一样:无法通过变量名找到该变量,但可以通过指针访问。其他文件还可以命名相同的变量名且不会冲突。
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复

使用道具 举报

24

主题

208

帖子

0

精华

高级会员

Rank: 4

积分
714
金钱
714
注册时间
2014-4-8
在线时间
160 小时
 楼主| 发表于 2016-4-20 14:50:56 | 显示全部楼层
指针函数或者是函数指针的概念我都明白,只是他用这样的方法去调用一个静态函数,为何不让那个被调用的函数变成extern,然后直接调用,static的功能好像就那么几个,所以想不通为什么用这样的方法
回复

使用道具 举报

24

主题

208

帖子

0

精华

高级会员

Rank: 4

积分
714
金钱
714
注册时间
2014-4-8
在线时间
160 小时
 楼主| 发表于 2016-4-20 15:38:43 | 显示全部楼层
ianhom 发表于 2016-4-20 15:21
我的理解是,用static修饰的函数仅本文件可见,即其他函数调用test_led()也不会调用到你static修饰的这个函 ...

我觉得你的解释有点牵强,若一个人写了一个test_led,这个函数是extern的,另外的一个人也写一个函数,名字重复了,编译器直接报错,这样来的更实在,更何况函数的命名是规则的,一般不会重复。我想一定不是因为还怕重名而这样进行程序设计,一定有别的意义。
回复

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
发表于 2016-4-20 16:53:05 | 显示全部楼层
xinxian 发表于 2016-4-20 15:38
我觉得你的解释有点牵强,若一个人写了一个test_led,这个函数是extern的,另外的一个人也写一个函数,名 ...

模块化设计的时候,每个人只会开发自己的模块,命名重复是很正常的事,extern的函数就是可以让别人通过函数名访问的,而static后的函数,即使知道这个函数名,也无法在其他文件中调用,这是为了安全性考虑。
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复

使用道具 举报

24

主题

208

帖子

0

精华

高级会员

Rank: 4

积分
714
金钱
714
注册时间
2014-4-8
在线时间
160 小时
 楼主| 发表于 2016-4-20 17:30:07 | 显示全部楼层
回复

使用道具 举报

58

主题

6293

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11475
金钱
11475
注册时间
2014-4-1
在线时间
1297 小时
发表于 2016-4-20 19:59:57 | 显示全部楼层


抱歉,辜负你信任了。

我c语言都是自学,用到什么学什么,
好在平时只用到 if-else,switch,基本一切搞定。

再次抱歉!

回复

使用道具 举报

307

主题

1427

帖子

12

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
7875
金钱
7875
注册时间
2015-10-15
在线时间
2874 小时
发表于 2016-4-20 21:05:46 | 显示全部楼层
5楼的解释很合理哦。。。static的很重要的作用就是限制可见范围。。。你可以百度一下。。。很容易理解
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

24

主题

208

帖子

0

精华

高级会员

Rank: 4

积分
714
金钱
714
注册时间
2014-4-8
在线时间
160 小时
 楼主| 发表于 2016-4-21 09:29:16 | 显示全部楼层
openedvadmin 发表于 2016-4-20 21:05
5楼的解释很合理哦。。。static的很重要的作用就是限制可见范围。。。你可以百度一下。。。很容易理解

上面的说法,我懂。那个是static的基本用法,我总是觉得不是那么简单的,我现在在看静态函数在ARM中的存储方式,另外,static在中断中的话,看看内核的出栈和入栈,不知道有没有什么疏忽,如有收获,我会在这个上面写出来,同事@所有人。我现在怎么觉得我有点魔障呢……
回复

使用道具 举报

24

主题

208

帖子

0

精华

高级会员

Rank: 4

积分
714
金钱
714
注册时间
2014-4-8
在线时间
160 小时
 楼主| 发表于 2016-4-21 09:31:01 | 显示全部楼层
xuande 发表于 2016-4-20 19:59
抱歉,辜负你信任了。

我c语言都是自学,用到什么学什么,

不用说抱歉的。这又有什么,谢谢你看我的帖子。一起学习就是!
回复

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
发表于 2016-4-21 14:51:35 | 显示全部楼层
本帖最后由 ianhom 于 2016-4-21 14:55 编辑

楼主是位细心的人~

一般来说static主要是写给编译器看的,让编译器对众多源码文件有明确的编译连接行为。对于不同的平台和编译器可能有不同的底层实现,但从语言角度上来说,static的作用就是限制函数的可见范围,避免命名重复和不安全的调用,这是所有平台和编译器应该提供的基本效果。当然不排除平台或编译器会为static做更多的优化,所以说楼主细心,精益求精。

这里我挑一例说明一下:ARM Cortex-M0+内核,IAR开发环境,standard C99
QQ截图20160421134912.png QQ截图20160421134927.png

static对函数存放位置的影响:
static有静态的意思,用static修饰的变量会和放入RAM中的全局/静态储存区,确保变量有完整的生命周期(作用域可能不同);而函数本身在单片机一般是存在于ROM中,不论是否有static修饰,都是一直存在的,所以在此例中static修饰的函数没有必要存放到其他地方。根据实验的效果可以看出,不论是否用static修饰,编译后test函数在ROM中的地址都是相同的。所以此例中static不影响函数的存放位置。
QQ截图20160421111723.png 左图为不带static修饰的test

QQ截图20160421112002.png 左图为带static修饰的test

static函数调用和退出时,入栈和出栈行为:

从上面两幅图中的汇编中可以看出,static函数和非static函数的调用时的入栈行为,以及函数退出时的出栈行为是一致的。所以此例中static不影响函数调用时CPU的行为。

static函数运行过程中,发生中断,入栈和出栈行为:
为了方便试验,在test函数中增加while(1),使用1ms定时器中断,同时为了确保编译后确实有压栈操作,在中断函数中增加数个临时变量,并在中断中增加对临时变量的操作以确保临时变量不被编译器优化掉。从实验结果来看,在test运行时,发生定时器中断,到中断退出,有无static修饰的入栈和出栈操作是相同的,所以在此例中,static不影响函数被中断后的处理。
QQ截图20160421114248.png 左图为不带static修饰的test

QQ截图20160421114344.png 左图为带static修饰的test

就以上仅有的三个方面来看,在此例中,static没有对函数的存放位置和运行的效果有更多的影响。当然不排除其他方面的影响和不同平台编译器的不同底层实现,楼主可以深入研究、分享。

还用此例再来看看static基本的效果:
下图是无static修饰的test函数,在其他文件中可以声明并调用test,编译运行均无异常。
QQ截图20160421131629.png

下图是带static修饰的test函数,在其他文件中即使extern声明,也无法通过编译,test仅能在本文件中可见。
QQ截图20160421131828.png

下面几张图是在两个文件中分别编写的test函数,都使用static修饰。虽然同名,但编译器可以通过static关键字找到正确的test函数进行连接。最后一张是map文件,可以看出同名的test函数在ROM中的地址是不一样的,两个函数实体。
QQ截图20160421132327.png
QQ截图20160421132554.png
QQ截图20160421132654.png
由此可见static限制的函数可见范围,但通过指针依旧可以进行访问,这样回答了楼主最初的问题,为什么要这样调用函数。感谢楼主的深入!

最后在结合自身的经历谈谈static,为了提高开发效率和软件可靠性,有点规模的单片机软件都采用模块化设计,这样每个软件模块都是很独立的存在,不能影响上层程序和其他模块。其中命名重复是比较直接的影响。曾经一个项目要使用两个已经实用的模块,分别来自不同的项目,而这两个模块中都有一个函数Sw_Tm_Init,一个是“开关(switch)定时器(timer)初始化”,另一个是“软件(software)时钟(time)初始化”,结果两个模块放一起编译的时候就出错,而修改任何一个模块的函数命名都会涉及到这个模块及其模块使用者软件版本的维护。虽然我们可以通过一定制度对函数名称有一定规范,但对于使用开源的代码,或开发人数较多的项目,仅靠规定很难完全控制。再者,C从语言本身的角度上提供的static这样机制,就不需要再劳烦项目经理唠叨啦。

以上个人拙见,抛砖引玉,望大神指正,做更多分享。



机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
发表于 2016-4-21 14:55:18 | 显示全部楼层
@xuande
大神太谦虚了
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复

使用道具 举报

24

主题

208

帖子

0

精华

高级会员

Rank: 4

积分
714
金钱
714
注册时间
2014-4-8
在线时间
160 小时
 楼主| 发表于 2016-4-21 15:31:25 | 显示全部楼层
@xuande 大神谦虚了
回复

使用道具 举报

24

主题

208

帖子

0

精华

高级会员

Rank: 4

积分
714
金钱
714
注册时间
2014-4-8
在线时间
160 小时
 楼主| 发表于 2016-4-21 15:32:28 | 显示全部楼层
@ianhom 谢谢  都是大神  我还太年轻……哈哈哈哈……真心感谢……说的也是,我为啥要查资料啊,自己写程序,自己跑跑就知道了……谢谢!!
回复

使用道具 举报

24

主题

208

帖子

0

精华

高级会员

Rank: 4

积分
714
金钱
714
注册时间
2014-4-8
在线时间
160 小时
 楼主| 发表于 2016-4-21 15:37:51 | 显示全部楼层
从开始学习32到现在   已经2年了  看看以前自己的帖子  真是  一步一步走到现在   真心迷茫过   谢谢大家  
回复

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
发表于 2016-4-21 18:05:44 | 显示全部楼层
谢谢个人大神的分享及指点,受益匪浅
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-2-26 23:22

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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