OpenEdv-开源电子网

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

全局变量定义的比较多,怎么优化代码??

[复制链接]

41

主题

278

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2357
金钱
2357
注册时间
2019-10-29
在线时间
380 小时
发表于 2020-12-23 16:53:22 | 显示全部楼层 |阅读模式
1金钱
在项目中有好几个地方(.c文件)中需要调用这些参数,像功率、信号强度.....,然后我全定义的全局变量,但是后面这些全局变量定义的越来越多了,那该怎么优化呢??
请教下各位,在项目中好几个.c文件中都要调用某一个参数,大家是用什么方法来传递的呢??

最佳答案

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

70

主题

6763

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
13138
金钱
13138
注册时间
2012-11-26
在线时间
3814 小时
发表于 2020-12-23 16:53:23 | 显示全部楼层
回复

使用道具 举报

0

主题

19

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
208
金钱
208
注册时间
2019-6-5
在线时间
70 小时
发表于 2020-12-23 19:45:46 | 显示全部楼层
extern
回复

使用道具 举报

3

主题

821

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3369
金钱
3369
注册时间
2011-11-10
在线时间
207 小时
发表于 2020-12-23 23:15:30 | 显示全部楼层
还是用结构体吧,优化代码,程序是给人读的。
回复

使用道具 举报

41

主题

278

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2357
金钱
2357
注册时间
2019-10-29
在线时间
380 小时
 楼主| 发表于 2020-12-24 09:20:16 | 显示全部楼层

结构体也会占用比较多的空间吧,我最初也是这样想说把相同类型的变量放到一个结构体中去,这样的话就更容易管理变量。
大佬  有个疑问,你们平常写代码也是通过全局变量来实现不同.c文件的传递吗?在有些帖子上看到说尽量不要用太多全局变量,不过我感觉全局变量用的太舒服了,直接一个全局变量太方便了
回复

使用道具 举报

5

主题

269

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1053
金钱
1053
注册时间
2020-5-11
在线时间
253 小时
发表于 2020-12-24 09:52:10 | 显示全部楼层
chenyuan 发表于 2020-12-24 09:20
结构体也会占用比较多的空间吧,我最初也是这样想说把相同类型的变量放到一个结构体中去,这样的话就更容 ...

结构体吧。有的时候全局变量用着相对方便。但后期代码可读性我感觉不如结构体。至少让后人看的明朗点。
回复

使用道具 举报

14

主题

141

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1126
金钱
1126
注册时间
2015-12-20
在线时间
119 小时
发表于 2020-12-24 09:56:40 | 显示全部楼层
我尽力不用全局变量(extern),除了一些经常调用的才使用。

方法:
1、合理放置变量位置,合并同样功能模块。
如:Control.c,把很多相关底层计算统一放入。Display.c,只做显示用。
2、使用接口函数
通过函数方式获取另一模块的变量数据。
如:Display.c想获取Control.c功率值
我在Control.c建立一个GetPowerVal();函数,用于获取功率值。
回复

使用道具 举报

41

主题

278

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2357
金钱
2357
注册时间
2019-10-29
在线时间
380 小时
 楼主| 发表于 2020-12-24 11:22:07 | 显示全部楼层
网络孤客 发表于 2020-12-24 09:56
我尽力不用全局变量(extern),除了一些经常调用的才使用。

方法:

好的  谢谢啦
回复

使用道具 举报

41

主题

278

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2357
金钱
2357
注册时间
2019-10-29
在线时间
380 小时
 楼主| 发表于 2020-12-24 11:22:31 | 显示全部楼层
thisisdemo 发表于 2020-12-24 09:52
结构体吧。有的时候全局变量用着相对方便。但后期代码可读性我感觉不如结构体。至少让后人看的明朗点。

好的 谢啦
回复

使用道具 举报

41

主题

278

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2357
金钱
2357
注册时间
2019-10-29
在线时间
380 小时
 楼主| 发表于 2020-12-24 11:22:52 | 显示全部楼层
c2007s 发表于 2020-12-23 23:15
还是用结构体吧,优化代码,程序是给人读的。

谢谢啦
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2020-12-24 13:54:21 | 显示全部楼层
用结构体, 不只是优化了可读性, 它更优化了速度及代码的size
回复

使用道具 举报

41

主题

278

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2357
金钱
2357
注册时间
2019-10-29
在线时间
380 小时
 楼主| 发表于 2020-12-24 14:10:19 | 显示全部楼层
edmund1234 发表于 2020-12-24 13:54
用结构体, 不只是优化了可读性, 它更优化了速度及代码的size

优化了代码的大小??
我记得结构体中,如果定义了 char 、u32...这个结构体的空间不是还要大点吗?
  1. struct unknown {
  2.     int a;
  3.     char b;
  4.     int c;
  5.     long d;
  6.     char e;
  7. };
  8. printf("%lu\n", sizeof(struct unknown));
复制代码

结构体重共有一个long类型,两个char类型,两个int类型成员。如果只按照这几个成员大小相加,结构体大小应该是4+1+4+4+1=14个字节大小。但实际上该结构体是20个字节大小。
回复

使用道具 举报

3

主题

808

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3888
金钱
3888
注册时间
2017-3-7
在线时间
1694 小时
发表于 2020-12-24 15:22:36 | 显示全部楼层
chenyuan 发表于 2020-12-24 14:10
优化了代码的大小??
我记得结构体中,如果定义了 char 、u32...这个结构体的空间不是还要大点吗?

这个可以调整或者设置字节对齐,问题倒不大,结构体可能管理起来好点,但是7#方式好点
回复

使用道具 举报

41

主题

278

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2357
金钱
2357
注册时间
2019-10-29
在线时间
380 小时
 楼主| 发表于 2020-12-24 16:18:01 | 显示全部楼层
a5820736 发表于 2020-12-24 15:22
这个可以调整或者设置字节对齐,问题倒不大,结构体可能管理起来好点,但是7#方式好点

好的  谢谢各位的宝贵意见啦
回复

使用道具 举报

3

主题

312

帖子

0

精华

高级会员

Rank: 4

积分
907
金钱
907
注册时间
2011-10-19
在线时间
196 小时
发表于 2020-12-24 16:33:34 | 显示全部楼层

加个结构体的优化并不彻底。模块化编程要注重模块间的隔离,不提倡跨源文件直接访问全局变量。
真正优化的方式是,每个全局变量都加static关键字修饰,即只允许本源文件内直接访问,其他源文件只能通过接口访问。
这样优化时就会自然而然地在这些接口上使用结构体将相关的变量整合起来。
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2020-12-24 18:21:04 | 显示全部楼层
chenyuan 发表于 2020-12-24 14:10
优化了代码的大小??
我记得结构体中,如果定义了 char 、u32...这个结构体的空间不是还要大点吗?

代码的Size, 不是内存
ARM的特性是只能在寄存器之间运算, 但是从内存加载到寄存器要通过这两步
一, 加载32位地址到寄存器, 两个指令周期
二, 从寄存器指定的地址加载到寄存器, 两个指令周期

理论上每一个变量都需要这两步, 但如果你加载的是一结构体, 只需要做一次(一)加载结构体的基地址就可以了,整个结构体的成员, 都可以通过基地址加偏移的方法只做(二)就行了。 所以你的代码变小了, 速度也快了。
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2020-12-24 18:41:48 | 显示全部楼层
chenyuan 发表于 2020-12-24 14:10
优化了代码的大小??
我记得结构体中,如果定义了 char 、u32...这个结构体的空间不是还要大点吗?

结构体重共有一个long类型,两个char类型,两个int类型成员。如果只按照这几个成员大小相加,结构体大小应该是4+1+4+4+1=14个字节大小。但实际上该结构体是20个字节大小。

除非你加了 __packed, 否则是不会用20个字节的
回复

使用道具 举报

41

主题

278

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2357
金钱
2357
注册时间
2019-10-29
在线时间
380 小时
 楼主| 发表于 2020-12-25 09:15:48 | 显示全部楼层
edmund1234 发表于 2020-12-24 18:21
代码的Size, 不是内存
ARM的特性是只能在寄存器之间运算, 但是从内存加载到寄存器要通过这两步
一, ...

好的  明白啦  谢谢大佬
回复

使用道具 举报

41

主题

278

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2357
金钱
2357
注册时间
2019-10-29
在线时间
380 小时
 楼主| 发表于 2020-12-25 18:32:19 | 显示全部楼层
ufbycd 发表于 2020-12-24 16:33
加个结构体的优化并不彻底。模块化编程要注重模块间的隔离,不提倡跨源文件直接访问全局变量。
真正优化 ...

找到关于全局变量的一些解释:
全局变量定义在函数体外部,在全局数据区分配存储空间,且编译器会自动对其初始化。
1.普通全局变量对整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量)。
2.静态全局变量仅对当前文件可见,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响。

你说的本源文件应该是指当前这个.c文件吧,那么按照你说的这个全局变量加static 那不是只有这个.c文件可以使用吗?那如果说另一个文件(2.c文件),要使用这个变量的话不是调用不了吗?那怎么实现多个.c文件的一个数据传输呢?
回复

使用道具 举报

3

主题

312

帖子

0

精华

高级会员

Rank: 4

积分
907
金钱
907
注册时间
2011-10-19
在线时间
196 小时
发表于 2020-12-25 20:26:37 | 显示全部楼层
chenyuan 发表于 2020-12-25 18:32
找到关于全局变量的一些解释:
全局变量定义在函数体外部,在全局数据区分配存储空间,且编译器会自动对 ...

C语言编程的一个基本原则:尽可能多的使用如下两个关键字,static、const 。如果不理解的话,建议如下:
去网上找些大公司的编程规范看看,如华为的C语言程序规范;
多看些编程书籍,如《C缺陷与陷阱》《人月神话》《Unix编程艺术》之类,了解一些编程的原则、思想及至哲学;
找些有名的开源项目,看看其代码;

回复

使用道具 举报

8

主题

154

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
439
金钱
439
注册时间
2018-12-21
在线时间
126 小时
发表于 2020-12-25 22:16:48 | 显示全部楼层
edmund1234 发表于 2020-12-24 18:21
代码的Size, 不是内存
ARM的特性是只能在寄存器之间运算, 但是从内存加载到寄存器要通过这两步
一, ...

不是很同意这个说法,实际上结构体与若干个数据在内存中的结构没啥区别,因为经常需要一起访问的数据,编译器会自动分配到一起,使用时确定这一块数据区的首地址就可以访问全部的内容,所以用不用结构体主要是为了方便人去理解,机器码其实没有本质区别。
我一般写程序也是这样做的,我用ASM写代码,直接操作寄存器,我也引入了结构体的概念但是本质上没有什么不同,无非是合理组织数据结构使访问便捷而已。
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2021-1-30 11:43:53 | 显示全部楼层
本帖最后由 edmund1234 于 2021-1-30 11:45 编辑
0x00000000 发表于 2020-12-25 22:16
不是很同意这个说法,实际上结构体与若干个数据在内存中的结构没啥区别,因为经常需要一起访问的数据,编 ...

你意思是不管是全局变量或不同的结构体, 在某函数的运行中都只用一个基地址? 所以才有不管是全局变量或结构都是一样的结论。

读写结构体内的成员, 只用一基地址(除非结构体大于4K), 再加一个局部变量, 它又需要重新加载
同一段代码, 上图是读取同一结构体下的几个成员,下图是把其中一个结构体成员改为全局变量, 比较一下两图右边代码, 看看是否你所认为的编译器会帮你做点什么?

读结构体成员.png
读全局变量.png
回复

使用道具 举报

8

主题

154

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
439
金钱
439
注册时间
2018-12-21
在线时间
126 小时
发表于 2021-1-31 08:54:27 | 显示全部楼层
edmund1234 发表于 2021-1-30 11:43
你意思是不管是全局变量或不同的结构体, 在某函数的运行中都只用一个基地址? 所以才有不管是全局变量或 ...

你这说明不了什么,你这只是单纯地修改了一个参数来源从结构体变成全局变量,你把所有参数改成全局变量再试试?上面三个全部是结构体,那么基地址肯定也是它附近的,而你最后一个全局变量的地址不一定能被寻址到,所以只能重新加载地址了。
如果还是做不到,只能说明几个问题:一是编译器过于垃圾,没办法做好优化;二是优化等级不够·,优化特性设置不正确;三是这些全局变量在其它多出代码均有访问,所以没办法优化为使得这一处访问最便捷的形式,而是考虑了全局最佳。
反正这段C,你让我用ASM全部重写对我来说结构体和全局真没什么区别,只看这一段我肯定会吧独立的全局变量像结构体那样分配到一段连续的空间里,方便访问。
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-29 17:43

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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