搜索
bottom↓
楼主: typedef

如何尽量地避免使用全局变量呢?

  [复制链接]

出0入0汤圆

发表于 2014-10-2 01:39:26 | 显示全部楼层

太多的全局换一拨人后,维护他就是灾难。

=================

出0入14汤圆

发表于 2014-10-2 02:53:58 来自手机 | 显示全部楼层
dxgdsx 发表于 2014-9-28 16:06 使用一个get_xxx和set_xxx接口函数应该可以防止全局变量漫天飞吧。

你这两个函数的具体也是操 作全局变量啊,要不然怎么传递信息?跟直接用全局变量有区别??

出0入14汤圆

发表于 2014-10-2 02:58:59 来自手机 | 显示全部楼层
qlb1234 发表于 2014-9-28 16:10 將這箇全局變量刪掉,看你怎麼實現和原來一樣的功能。

我反正是想不出来,举个最简单的例子,在timer.c里面有个定时器计数cnt,在user.c里面调用——这个很多人都会用这个结构,除去全局变量cnt,我是不知道怎么弄了

出0入14汤圆

发表于 2014-10-2 03:01:04 来自手机 | 显示全部楼层
pandong 发表于 2014-9-28 16:19 我觉得需要好好考虑你的程序,我遇到一个例子,就是用函数参数传递,去掉一个全局变量的。 ...

希望看下例子,想学习下

出0入14汤圆

发表于 2014-10-2 03:19:24 来自手机 | 显示全部楼层
typedef 发表于 2014-9-28 17:27 这个“最怕在多个模块中直接操作全局变量,这样会把各个模块之间的逻辑关系搞复杂!” 才是我现在最头痛 ...

直接操作和间接操作根本就没区别,总之就是有逻辑关系才需要操作,你不可能说把三个模块之间的关系砍成两个,另一个不理它

我觉得全局变量满天飞是由程序的复杂性决定的,这个是改变不了的,只要有很多个模块有共同的地方,需要体现他们之间的逻辑,那么我觉得无论是用全局变量还是其他方式来体现,都会感到头痛,所以我觉得重点不是去掉全局变量(有些全局变量是必须存在的),而是要想办法改变程序的结构,使得各个模块之间的脉络清晰可见…

出0入14汤圆

发表于 2014-10-2 03:22:38 来自手机 | 显示全部楼层
YZDREAM8 发表于 2014-9-28 22:18 给全局变量换个马甲仍然是全局变量呀。我觉得在程序结构及算法上多下点功夫才是正道。 ...

这个才说到点上了

出0入14汤圆

发表于 2014-10-2 03:25:25 来自手机 | 显示全部楼层
Gorgon_Meducer 发表于 2014-9-29 01:03 使用二楼的方法,好处非常多,不仅不会降低效率,还会降低代码尺寸, 实现对变量的访问权限控制(只读,只写 ...

我很想知道你们是怎么实现的,能不能给个基本的实现例程?

出0入14汤圆

发表于 2014-10-2 03:34:06 来自手机 | 显示全部楼层
qlb1234 发表于 2014-9-29 10:21 將對全局變量的訪問,替換成用函數訪問,或者是放入結構體,這都無法從根本上解決問題。 等一下,甚麼問題 ...

可乐问题根本就不是全局变量的问题,是由于需求不明,项目开发没考虑全的后果

出0入0汤圆

发表于 2014-10-2 05:02:49 | 显示全部楼层
给个基本的实现例程

出0入0汤圆

发表于 2014-10-2 07:15:12 | 显示全部楼层
dxgdsx 发表于 2014-9-28 16:06
使用一个get_xxx和set_xxx接口函数应该可以防止全局变量漫天飞吧。

有点像java等高级语言的感觉

出0入0汤圆

发表于 2014-10-2 11:42:39 | 显示全部楼层
isakura 发表于 2014-10-2 02:53
你这两个函数的具体也是操 作全局变量啊,要不然怎么传递信息?跟直接用全局变量有区别?? ...

良好的编码,只是为了让人更好的维护代码,或者让团队之间更好的合作。
本质上代码都是编译成二进制,对机器来说是没有区别的。
个人觉得,对于语言来说有静态变量或者全局变量之类的概念。对于一个事物比如一个设备的参数,那它就是一个全局存在的参数,你可以消除全局变量,但是你不能消除这个设备的参数。
我们要做的就是有效维护好这个全局的参数,防止随意修改从而导致难以维护。

出0入0汤圆

 楼主| 发表于 2014-10-6 09:29:34 | 显示全部楼层
dxgdsx 发表于 2014-10-2 11:42
良好的编码,只是为了让人更好的维护代码,或者让团队之间更好的合作。
本质上代码都是编译成二进制,对 ...

对,就是这样,防止随意的修改从而导致出错和难以维护

出0入0汤圆

发表于 2014-10-6 11:07:39 | 显示全部楼层
比较倾向于62楼的

出0入14汤圆

发表于 2014-10-6 22:08:25 | 显示全部楼层
dxgdsx 发表于 2014-10-2 11:42
良好的编码,只是为了让人更好的维护代码,或者让团队之间更好的合作。
本质上代码都是编译成二进制,对 ...

这个我能理解,你这样写只是让人养成不直接对参数用=赋值,而是通一个函数来操作,类似于单片机io口或者外设的操作方式,一个是直接操作寄存器,一个是通过库函数来的……对不对?不过只是这样还是无法解决逻辑混乱的问题…我想大部分的程序无法解读并不是因为全局变量满天飞,而是对于程序的构造没有层次感

出0入0汤圆

发表于 2014-10-6 23:12:52 | 显示全部楼层
dxgdsx 发表于 2014-9-28 16:06
使用一个get_xxx和set_xxx接口函数应该可以防止全局变量漫天飞吧。

linux的许多驱动都是这样做的  不错!

出0入42汤圆

发表于 2014-10-7 07:53:29 来自手机 | 显示全部楼层
受益匪浅啊

出0入0汤圆

发表于 2014-10-7 11:17:18 | 显示全部楼层
kebaojun305 发表于 2014-9-28 17:56
最好的方法是封装到一个结构体中,一个功能模块的变量全部封装到里面, 其他模块要修改变量,就全部使用对 ...

赞一个,这种方式确实不错啊,小型程序用一些全局变量,感觉没什么不清楚的,只是程序大了,结构复杂了,容易产生莫名其妙的耦合关系, 其实最主要的还是得自己脑子清醒,

出0入0汤圆

发表于 2014-10-8 14:35:00 | 显示全部楼层
对啊,小工程用用全局变量,只要头脑清醒,应该不会出问题,我都是带着纸和笔,记着变量的逻辑关系。大工程还是封装上吧。

出0入296汤圆

发表于 2014-10-8 17:13:36 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2014-10-8 17:14 编辑
isakura 发表于 2014-10-2 02:58
我反正是想不出来,举个最简单的例子,在timer.c里面有个定时器计数cnt,在user.c里面调用——这个很多人 ...


timer.c

  1. static volaitle uint32_t s_wCounter;

  2. ISR(Timer0_vect)
  3. {
  4.     s_wCounter++;
  5. }

  6. uint32_t get_counter(void)
  7. {
  8.     uint32_t wResult;
  9.     SAFE_ATOM_CODE(                           //! 原子操作的保护宏
  10.         wResult = s_wCounter;
  11.     )
  12.     return wResult;
  13. }
复制代码



timer.h


  1. #ifndef __TIMER_H__
  2. #define __TIMER_H__

  3. extern uint32_t get_counter(void);


  4. #endif
复制代码

出0入0汤圆

发表于 2014-10-8 17:33:41 | 显示全部楼层
代码量小随便写都行,代码量大就得考虑封装问题了

出0入0汤圆

发表于 2014-10-8 17:42:41 | 显示全部楼层
Gorgon_Meducer 发表于 2014-9-29 01:03
使用二楼的方法,好处非常多,不仅不会降低效率,还会降低代码尺寸,
实现对变量的访问权限控制(只读,只写 ...

这个方法可以考虑试一下,有用的。。。

出0入14汤圆

发表于 2014-10-8 20:02:44 | 显示全部楼层

我真看不出这样写跟直接操作s_wCounter有什么区别,你这样只是通过一个函数来操作,一样需要存在全局变量,并不会产生什么优化…最多只是有助于理解,而这个可以通过好的变量名来解决…

我认为需要用到函数的地方就是用来封装特定的,需要多次运算的功能

对于大部分全局变量都只是单个操作不涉及其他的时候,是没有必要封装成函数的

出0入296汤圆

发表于 2014-10-8 23:24:23 | 显示全部楼层
isakura 发表于 2014-10-8 20:02
我真看不出这样写跟直接操作s_wCounter有什么区别,你这样只是通过一个函数来操作,一样需要存在全局变量 ...

我前面已经解释过了,不再做更详细的说明。有相应经验积累的人自然能看出差别,
我不强求,也没有愿望和义务说服你。所需的信息我已经全部给出,并无遗漏。

出0入0汤圆

发表于 2014-10-9 00:48:02 | 显示全部楼层
以前用51单片机, 总会省着点变量用。

等现在用STM8/32以后, 感觉变量这个问题,压根就不是个问题。  全部定成全局变量都够用!

所以, 习惯就好!  别太纠结这种问题!  

出0入0汤圆

发表于 2014-10-9 01:25:39 | 显示全部楼层
我的代码也是很多全局变量,现在努力优化中。

出0入0汤圆

发表于 2014-10-9 06:21:36 | 显示全部楼层
学习了,记得凌明的书中提到:大型软件由多人合作研发,为保证可靠性,一般不提倡用全局变量

出0入0汤圆

发表于 2014-10-9 08:29:33 | 显示全部楼层
很深奥的说。。。。努力理解中。

出0入0汤圆

发表于 2014-10-9 10:12:05 | 显示全部楼层
qlb1234 发表于 2014-9-28 16:11
編譯器喜歡全局變量,一箇地址就訪問到了。
不喜歡全局變量的,是人。
人設計機器,就是要讓機器做人不喜 ...

好似正解

出130入129汤圆

发表于 2014-10-9 10:15:36 | 显示全部楼层
主题应该是 如何避免直接操作全局变量?

出0入0汤圆

发表于 2014-10-9 10:17:41 | 显示全部楼层
全局变量也没什么不好,一些设置参数为全局变量比较好操作

出0入0汤圆

发表于 2014-10-9 10:54:33 | 显示全部楼层
让团队人员写代码养成同一种风格,大项目的维护和修改会很好

出0入0汤圆

发表于 2014-10-10 14:06:41 | 显示全部楼层
留记号。

出100入101汤圆

发表于 2014-10-10 14:14:52 | 显示全部楼层
Gorgon_Meducer 发表于 2014-9-29 01:03
使用二楼的方法,好处非常多,不仅不会降低效率,还会降低代码尺寸,
实现对变量的访问权限控制(只读,只写 ...

“降低代码尺寸”,这个貌似不理解。加入供外部模块读写的函数,代码应该变大才对?

出0入0汤圆

发表于 2014-10-10 15:51:07 | 显示全部楼层
yu_studio 发表于 2014-9-28 16:58
我一般把全局变量分类,用struct分成不同模块,看起来清爽多了。

我觉得这个办法 可行

出0入0汤圆

发表于 2014-10-10 16:28:55 | 显示全部楼层
最好用结构体归类,否则程序大了维护会很麻烦

出0入0汤圆

发表于 2014-10-10 17:24:35 | 显示全部楼层
模块化编程或者大项目尽量少用全局变量的好。

出0入0汤圆

 楼主| 发表于 2014-10-13 14:33:48 | 显示全部楼层
gongngei 发表于 2014-10-10 16:28
最好用结构体归类,否则程序大了维护会很麻烦


现在用 结构体 加 函数接口的方式来实现

出0入0汤圆

发表于 2014-10-14 14:27:22 | 显示全部楼层
定义结构体封装好,定义接口函数处理,应该可以吧

出0入0汤圆

发表于 2014-10-14 14:58:57 | 显示全部楼层
全局变量挺好的,只要标清好区分就行了

出0入0汤圆

 楼主| 发表于 2014-10-14 15:46:16 | 显示全部楼层
LiuYH 发表于 2014-10-14 14:27
定义结构体封装好,定义接口函数处理,应该可以吧

现在就是用这种方式实现的

出0入0汤圆

 楼主| 发表于 2014-10-14 15:46:45 | 显示全部楼层
大金贝 发表于 2014-10-14 14:58
全局变量挺好的,只要标清好区分就行了

多了久了好麻烦

出0入0汤圆

发表于 2014-10-14 23:03:21 来自手机 | 显示全部楼层
受教了,要好好消化一下。

出0入0汤圆

发表于 2014-10-30 23:39:56 | 显示全部楼层
程序不大的话,应该关系不大

出0入0汤圆

发表于 2014-10-31 08:59:26 | 显示全部楼层
收获颇丰 谢谢大神们

出0入0汤圆

发表于 2014-10-31 09:01:00 | 显示全部楼层
dxgdsx 发表于 2014-9-28 16:06
使用一个get_xxx和set_xxx接口函数应该可以防止全局变量漫天飞吧。

这个习惯非常好!

出0入0汤圆

发表于 2014-10-31 09:13:43 | 显示全部楼层
主要还是看你设计的这个变量的作用范围需要是多大,我的快习贯是尽量使用局部变量,有时为了提高运行效率会多使用全局变量,但是也可以限定在一个文件内,用静态变量

出0入0汤圆

发表于 2014-10-31 09:17:17 | 显示全部楼层
mark,学习了

出0入8汤圆

发表于 2014-10-31 09:18:56 | 显示全部楼层
isakura 发表于 2014-10-6 22:08
这个我能理解,你这样写只是让人养成不直接对参数用=赋值,而是通一个函数来操作,类似于单片机io口或者 ...

你的这种问题 就不是全局变量的问题,还是程序结构的问题,或者说是 程序模块的划分问题。

出0入0汤圆

发表于 2014-10-31 10:49:24 | 显示全部楼层
平时没注意这个问题,以后要注意了

出5入8汤圆

发表于 2014-10-31 10:51:36 来自手机 | 显示全部楼层
c的变量的作用域控制功能弱,需要开发人员注意

出0入0汤圆

 楼主| 发表于 2014-11-3 08:28:16 | 显示全部楼层
arm_m0 发表于 2014-10-31 09:13
主要还是看你设计的这个变量的作用范围需要是多大,我的快习贯是尽量使用局部变量,有时为了提高运行效率会 ...


我现在是,写之前先想好程序架构,分好层次,构思好每个模块的数据结构,在单文件内使用static变量或结构。需要外部模块来修改参数的时候,就使用函数接口来实现。

出0入296汤圆

发表于 2014-11-3 10:45:58 | 显示全部楼层
typedef 发表于 2014-11-3 08:28
我现在是,写之前先想好程序架构,分好层次,构思好每个模块的数据结构,在单文件内使用static变量或结 ...

就应该是这种方式,赞!做事很专业哈!

出0入0汤圆

发表于 2014-11-3 11:02:07 来自手机 | 显示全部楼层
可以看看static关键字的用法,这个可以减少全局变量的使用

出0入0汤圆

发表于 2014-11-3 11:14:55 | 显示全部楼层
全局变量在换人之后,是个非常麻烦的事情

出0入0汤圆

 楼主| 发表于 2014-11-4 15:30:49 | 显示全部楼层
Gorgon_Meducer 发表于 2014-11-3 10:45
就应该是这种方式,赞!做事很专业哈!

谢谢您的鼓励!正在坚持学习  “无(No)节(Just)操(Coding)”

出0入0汤圆

发表于 2014-11-5 12:09:49 | 显示全部楼层
要做好模块化,全局变量只能本模块内用,其他模块调用需要通过接口,这样就不乱了。

出0入0汤圆

发表于 2014-11-5 12:10:05 | 显示全部楼层
要做好模块化,全局变量只能本模块内用,其他模块调用需要通过接口,这样就不乱了。

出0入0汤圆

发表于 2014-11-5 12:45:17 | 显示全部楼层
本帖最后由 semilog 于 2014-11-5 12:48 编辑

没有详细看完所有的帖子,二楼的方法是个很好的办法,对于全局变量来作说,关注它的存储周期和作用范围,对于一个大的工程来说,还要考虑到变量的安全性,别人是不是可以调用?

还有就是如果是有操作系统的,还要关注变量的修改顺序,要不要加锁,等等,这些都要考虑。最好的就是加static ,通过函数对外调用,可以方便管理,并加以保护

出0入0汤圆

发表于 2014-11-5 13:00:08 | 显示全部楼层
semilog 发表于 2014-11-5 12:45
没有详细看完所有的帖子,二楼的方法是个很好的办法,对于全局变量来作说,关注它的存储周期和作用范围,对 ...

你怎么使用的get和set的?

出0入0汤圆

发表于 2014-11-5 13:29:51 | 显示全部楼层
好吧,只是举个例子,不加互斥量,如下:

static uint32_t g_cell_voltage = 600;

void set_cell_voltage(uint32_t value)
{
        g_cell_voltage = value;
}

uint32_t get_cell_voltage(void)
{
        return g_cell_voltage;
}

出0入0汤圆

发表于 2014-11-5 13:30:43 | 显示全部楼层
本帖最后由 mvip 于 2014-11-5 13:31 编辑


高手能不能解释下这个程序,我们功底差的实在没看懂,特别是
ISR(Timer0_vect)
{
    s_wCounter++;
}

这个ISR(Timer0_vect)是什么

能得到您的指点迷津非常感谢

出0入0汤圆

发表于 2014-11-5 13:35:42 | 显示全部楼层
semilog 发表于 2014-11-5 13:29
好吧,只是举个例子,不加互斥量,如下:

static uint32_t g_cell_voltage = 600;

这个只是把一个变量封装成函数,能详细解释下。
请您多举点例子,非常感谢

出0入0汤圆

发表于 2014-11-5 14:26:01 | 显示全部楼层
typedef 发表于 2014-11-3 08:28
我现在是,写之前先想好程序架构,分好层次,构思好每个模块的数据结构,在单文件内使用static变量或结 ...

就这么干,此贴最佳回复。

出0入296汤圆

发表于 2014-11-5 16:10:26 | 显示全部楼层
mvip 发表于 2014-11-5 13:30
高手能不能解释下这个程序,我们功底差的实在没看懂,特别是
ISR(Timer0_vect)
{

  1. ISR(Timer0_vect)
  2. {
  3. ...
  4. }
复制代码

这只是一个常见的中断处理程序的格式而已,ISR是Interrupt Service Routine的缩写,Timer0_vect是定时器0的中断
向量。这两个和在一起的意思就是,这是一个Timer0_vect的中断处理程序。

出0入0汤圆

发表于 2014-11-5 20:16:47 | 显示全部楼层
mvip 发表于 2014-11-5 13:30
高手能不能解释下这个程序,我们功底差的实在没看懂,特别是
ISR(Timer0_vect)
{

首先,很久没有写AVR的程序了。其实对于这个问题,以前写AVR的程序的时候并没有深究,只是知道这个是avr-gcc用来定义中断函数的,

并不知道真正的内函是什么。你今天问了,我回过头来看这个函数定义,给我的感觉就是它是一个宏定义,用这个定义来申明中断函数。

我所以我看了一下代码,实事也是如此,见文件 winavr或avrstudio6下的arv-gcc安装目录:\avr\include\avr\interrupt.h 中:

......

#  define ISR(vector, ...)            \
    void vector (void) __attribute__ ((signal,__INTR_ATTRS)) __VA_ARGS__; \
    void vector (void)
.....

可以看到这里是先定义中断函数的属性,再定义中断函数名,具体的宏是如何定义的,我就不解释了,想知道的百度

这里可以看到,中断函数其实是有属性的,不过一般我们都不用,如果实在想知道,见文档:doc\avr-libc\avr-libc-user-manual\group__avr__interrupts.html

这个文件中有详细说明,并且说了关于avr-gcc编译器规定的所有的中断名的说明,很详细,很多AVR 的C语言的书就抄这个文档

出0入0汤圆

发表于 2014-11-7 08:45:25 | 显示全部楼层
全局变量不可怕 重点是模块化 逻辑清晰 注释准确到位

出0入0汤圆

 楼主| 发表于 2014-11-7 08:57:07 | 显示全部楼层
mvip 发表于 2014-11-5 13:35
这个只是把一个变量封装成函数,能详细解释下。
请您多举点例子,非常感谢 ...

可以看看傻孩子上面的回复

出0入0汤圆

 楼主| 发表于 2014-11-7 08:59:03 | 显示全部楼层
tiger2023 发表于 2014-11-7 08:45
全局变量不可怕 重点是模块化 逻辑清晰 注释准确到位

全局变量太多,模块之间的耦合性就加强了。当然使用接口函数,也一样会有耦合性,但对于维护,修改,升级等会方便很多

出0入0汤圆

发表于 2014-11-7 10:41:43 | 显示全部楼层
typedef 发表于 2014-11-7 08:59
全局变量太多,模块之间的耦合性就加强了。当然使用接口函数,也一样会有耦合性,但对于维护,修改,升级 ...

恩 确实是这样的 程序规模大了之后 难免会有一些全局变量的

出0入0汤圆

发表于 2014-11-7 11:10:53 | 显示全部楼层
以前写小项目的时候,没这种感觉,后来,项目越来越大后,发现,全局变量的管理是个问题,写程序的要么记住,要么来回查看变量,后来发现了解决的方法,优化程序数据结构和框架,采用消息队列和堆栈,自动管理类似的全局变量!

出0入0汤圆

 楼主| 发表于 2014-11-7 13:04:25 | 显示全部楼层
yaoyutaoTom 发表于 2014-11-7 11:10
以前写小项目的时候,没这种感觉,后来,项目越来越大后,发现,全局变量的管理是个问题,写程序的要么记住 ...

采用消息队列和堆栈来管理类似的全局变量是怎么样实现的呢,可否提供例子供参考学习呢?

我自己的想法是,先建立一个模块并提供接口用来做模块/任务间的通信

如:   uint8_t message_send( uint8_t task_id, uint16_t len, void *pdat );
或:   uint8_t messgae_send( void (*task)(void), uint16_t len, void *pdat );

这样,当任务A需要传送数据给任务B的时候可以这样:

      message_send( 任务B的ID, 数据长度, 数据指针 );
      或
      message_send( 任务B, 数据长度, 数据指针 );


现在还没具体去实现,也不知道这样的可行性,感觉如果这样做,对内存的开销会比较大,目前工作所用的片子资源都不是那么多



      

出0入0汤圆

发表于 2014-11-7 20:24:07 | 显示全部楼层
“使用一个get_xxx和set_xxx接口函数应该可以防止全局变量漫天飞吧。”

好方法~~

出0入0汤圆

发表于 2014-11-7 21:10:54 来自手机 | 显示全部楼层
学习一下

出0入0汤圆

发表于 2014-11-7 21:21:37 | 显示全部楼层
最简单的一招:用两个函数替换一个全局变量,一个读,一个写。好处?易维护,易修改,易调试

出0入0汤圆

发表于 2014-11-10 09:14:48 | 显示全部楼层
typedef 发表于 2014-11-7 13:04
采用消息队列和堆栈来管理类似的全局变量是怎么样实现的呢,可否提供例子供参考学习呢?

我自己的想法是 ...

全局变量一般用在标志位和参数传递上,打个比喻,当你盖房子的时候,一般的小房子是以砖头为基本材料堆起的,当你盖大楼的时候,砖头是不是太小了,就应该以大的水泥块为基本材料盖才方便和舒服,程序也是一样,你为每一个状态设置一个标志位,就像以砖头为单位一样,如果你建立一个消息对列呢,就好像砖头封成了一个水泥块,他把各位状态标志在对列里自动分配,你就不用管理那些砖头,只要关注水泥块就行了!

出0入0汤圆

发表于 2014-11-10 09:25:11 | 显示全部楼层
学习一下,

出0入296汤圆

发表于 2014-11-13 00:35:35 | 显示全部楼层
semilog 发表于 2014-11-5 20:16
首先,很久没有写AVR的程序了。其实对于这个问题,以前写AVR的程序的时候并没有深究,只是知道这个是avr- ...

'ARM环境下现在也可以用类似的写法,只不过用的是weak的特性

出0入0汤圆

发表于 2014-11-13 07:33:34 | 显示全部楼层
请教傻孩子老师,单片机的外设寄存器是不是具有全局变量的特征呢,也可以说就是全局变量呢。像am335x的,几千个寄存器吧,也可以说是有几千个全局变量。还有一种情况是比方说定时器初始化函数和定时器中断函数不在一个文件中,这时候不用全局变量怎么解决呢。数据和函数是分不开的,如果一个项目数据用的乱七八糟的,那可想而知其函数结构肯定也不怎么样。我现在在开始一个新项目的代码时,都要先规划好代码书写规范、文件结构、数据结构、事务流程图、界面流程图,这样才能开始码字母。我也看过全局变量满天飞的代码,真费脑细胞。

出0入296汤圆

发表于 2014-11-13 20:40:36 来自手机 | 显示全部楼层
spcm 发表于 2014-11-13 07:33
请教傻孩子老师,单片机的外设寄存器是不是具有全局变量的特征呢,也可以说就是全局变量呢。像am335x的,几 ...

寄存器都是静态变量。全局变量是静态变量的一种。完全看你怎么限制它。你完全可以把针对寄存器的操作人为限定在模块中。从C指针技术的角度来说,只要是静态分配的变量(包括全局变量和各类static的变量),都可以借助指针访问,所谓的范围限制都是假的。从这个角度来说,即便是寄存器这种全局变量,你也可以通过技术手段将其限制在模块中(比如不公开头文件),或者通过规则限制住。关键在于用的人有没有封装的思想,不在于是否全局。

出0入0汤圆

发表于 2014-11-13 21:25:41 | 显示全部楼层
函数返回

出0入0汤圆

发表于 2014-11-13 21:35:54 | 显示全部楼层
好多高手的发言啊

出0入25汤圆

发表于 2014-11-13 22:22:34 | 显示全部楼层
本帖最后由 rei1984 于 2014-11-13 22:33 编辑
Gorgon_Meducer 发表于 2014-11-13 20:40
寄存器都是静态变量。全局变量是静态变量的一种。完全看你怎么限制它。你完全可以把针对寄存器的操作人为 ...


看了你上面的 程序。可以看出你是一位有经验的人士。类似于linux 专业coder。

对于你的贴出的程序,我做如下讲解:



  1. static volaitle uint32_t s_wCounter;      

  2. //以上在timer0.c 中开辟的 静态 全局变量,最为关键
  3. // 1.  static  表示,这个s_wCounter 全局变量,只能由timer.c里面的函数还进行(读/写) 操作
  4. // 2. volaitle   表示 ,让编译器不要优化访问此变量,也就是 编译器编译出的代码,每次访问s_wCounter 这个变量,是老老实实的去变量地址上读取or写入。  而绝对不会因为优化,去访问寄存器!   《===关于这里 不知道 我的理解 是否正确,个人觉得我的理解是 对的

  5. //3.  有趣的疑问:  开辟 这个  变量 static volaitle uint32_t s_wCounter;        如果改写成  volaitle  static uint32_t s_wCounter;    《===是否可以???  


  6. ISR(Timer0_vect)
  7. {
  8.     s_wCounter++;
  9. }


  10. uint32_t get_counter(void)
  11. {
  12.     uint32_t wResult;

  13.     SAFE_ATOM_CODE(                           //! 原子操作的保护宏
  14.         wResult = s_wCounter;
  15.     )

  16.     return wResult;
  17. }
复制代码




----------此外--------------------

  1. //关于傻孩子写的“从C指针技术的角度来说,只要是静态分配的变量(包括全局变量和各类static的变量),都可以借助指针访问,所谓的范围限制都是假的。”  //表示赞成,比如我解密别人的程序。  别人吧计算出的sn写在 局部变量内   ,同样我可以根据猜测 解密出 最终 开辟变量的地址, 从而用指针去 读取 or 写入变量!
复制代码








结束!

出0入0汤圆

发表于 2014-11-13 22:29:32 | 显示全部楼层
只能尽量避免用。

出0入0汤圆

发表于 2014-11-13 22:29:47 | 显示全部楼层
Gorgon_Meducer 发表于 2014-11-13 20:40
寄存器都是静态变量。全局变量是静态变量的一种。完全看你怎么限制它。你完全可以把针对寄存器的操作人为 ...

懂了,谢谢。

出0入296汤圆

发表于 2014-11-14 00:45:14 | 显示全部楼层
rei1984 发表于 2014-11-13 22:22
看了你上面的 程序。可以看出你是一位有经验的人士。类似于linux 专业coder。

对于你的贴出的程序,我做 ...

第三点你的疑问,交换后没有区别。需要小心的是申请指针变量时候的顺序

出0入0汤圆

发表于 2014-11-14 08:45:36 | 显示全部楼层
如果确实需要使用全局变量呢,而且多呢,建议使用结构体的方式,这样一是看起来清晰,二是好维护,如果数量少那就没必要了~

出0入0汤圆

发表于 2014-11-14 09:20:47 | 显示全部楼层
对于嵌入式系统而言这种情况就是应该用全局变量的

出0入0汤圆

 楼主| 发表于 2014-11-14 09:30:47 | 显示全部楼层
spcm 发表于 2014-11-13 07:33
请教傻孩子老师,单片机的外设寄存器是不是具有全局变量的特征呢,也可以说就是全局变量呢。像am335x的,几 ...

能推荐一个画流程图比较好的软件吗?

出0入0汤圆

 楼主| 发表于 2014-11-14 09:34:34 | 显示全部楼层
pengkewei 发表于 2014-11-14 08:45
如果确实需要使用全局变量呢,而且多呢,建议使用结构体的方式,这样一是看起来清晰,二是好维护,如果数量 ...


其实全局变量肯定是存在的,只是如果把它封装起来,使用函数/接口去访问,对程序的编写和后面的修改与维护,或是升级会更加方便。调试和排错也会更容易些,避免因为直接操作引起的混乱

出0入0汤圆

发表于 2014-11-14 09:53:06 | 显示全部楼层
isakura 发表于 2014-10-8 20:02
我真看不出这样写跟直接操作s_wCounter有什么区别,你这样只是通过一个函数来操作,一样需要存在全局变量 ...

他主要是想利用static 限定了全局变量的作用域在当前编译单元吧?

出0入0汤圆

发表于 2014-11-14 10:57:01 | 显示全部楼层
typedef 发表于 2014-11-14 09:30
能推荐一个画流程图比较好的软件吗?

visio,感觉不太好用,但一直在用

出0入0汤圆

 楼主| 发表于 2014-11-18 15:48:04 | 显示全部楼层
spcm 发表于 2014-11-14 10:57
visio,感觉不太好用,但一直在用

谢谢,看了一下,电脑上刚好有装这个软件,好像是2003版本的

出70入0汤圆

发表于 2014-11-18 22:43:16 | 显示全部楼层
timi 发表于 2014-10-6 23:12
linux的许多驱动都是这样做的  不错!

你这是读写IO吧。

出0入0汤圆

发表于 2014-11-25 10:24:20 | 显示全部楼层
typedef 发表于 2014-11-3 08:28
我现在是,写之前先想好程序架构,分好层次,构思好每个模块的数据结构,在单文件内使用static变量或结 ...

您好,请问可以分享一个例程吗,想好好学习一下你这种全局变量处理的思想

出0入0汤圆

 楼主| 发表于 2014-11-29 17:31:29 | 显示全部楼层
tdchenke 发表于 2014-11-25 10:24
您好,请问可以分享一个例程吗,想好好学习一下你这种全局变量处理的思想 ...


请参考62L和傻孩子版主的回同贴。

我比较懒,业余基本不写什么代码。都是工作上的程序

出0入0汤圆

发表于 2014-11-30 10:16:13 来自手机 | 显示全部楼层
楼主可以试一下用static静态变量

出0入0汤圆

发表于 2014-11-30 11:44:08 | 显示全部楼层
如果多的话,就做成静态全局变量,放到一个模块内,如果有逻辑关系,那也可以分散到各个模块中去,不过,需要单独做接口来读取和修改。

出0入0汤圆

发表于 2014-11-30 11:59:52 | 显示全部楼层
楼主的问题可改为,如何转变 编程的思路,由"面向过程"的方法转向"面向对象"的方法?
大量使用全局变量意味着,你编程时思考了整个时序过程,所以你知道怎么去用全局变量,这只是你的编程思路是这样。
但如果你希望你的程序被大多数“面向对象的”程序员看懂并复用,你需要开始思考什么是对象,什么是接口,什么是方法。。。。

出0入0汤圆

发表于 2014-11-30 12:01:49 来自手机 | 显示全部楼层
良好封装,预留接口函数,二楼方法很好

出0入0汤圆

发表于 2014-11-30 12:24:39 | 显示全部楼层
排队学习。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-24 21:09

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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