8784|21

57

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

不同模块用到的变量定义问题,这样做有无问题? [复制链接]

最近读到一些资料:永远不要在.h文件中定义变量!
正确的做法是:
/*m1.h*/
extern int a;
/*m1.c*/
#include "m1.h"
int a=5;
/*m2.c*/
#include "m1.h"//模块2中包含模块1的.h文件
/*m3.c*/
#include "m1.h"//模块3中包含模块1的.h文件

我想问一下,我这样做是否可以:
/*m1.h*/
int a;
/*m1.c*/
#include "m1.h"
int foo()
{
   a=5;//直接对该变量进行(赋值、运算、判断等)操作
   ...
}
/*m2.c*/
#include "m1.h"//模块2中包含模块1的.h文件
int fff()
{
   a=5;//直接对该变量进行(赋值、运算、判断等)操作
   ...
}
/*m3.c*/
#include "m1.h"//模块3中包含模块1的.h文件
此帖出自stm32/stm8论坛

最新回复

                                 H文件里肯定是不能定义变量的,要养成好的习惯  详情 回复 发表于 2010-4-7 15:43
点赞 关注
 

回复
举报

85

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
                                 疑问是,.h文件不能定义变量,而是申明变量(不会分配内存)。在我的用法里并没有在任何一个.c文件里定义了变量,这样使用编译是没有报错,不过不知道是否是可以的
此帖出自stm32/stm8论坛
 
 

回复

88

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
同样在一个.c文件里定义了一个函数,比如是
/*m1.c*/
int foo(int a)
{
   ;
}
我要在另一个函数里调用它,我在.文件里这样声明
/*m1.h*/
int foo(int a);

问:int foo(int a);前面需要加extern?
此帖出自stm32/stm8论坛
 
 

回复

85

帖子

0

TA的资源

一粒金砂(初级)

4
 
                                 这样的问题,自己写个TEST就知道了啊,用Cygwin很方便的啊
此帖出自stm32/stm8论坛
 
 
 

回复

77

帖子

0

TA的资源

一粒金砂(初级)

5
 
永远不要在.h文件中定义变量!

这是一个基本常识,因为.h文件可能会被多个.c文件引用,在.h文件中定义变量,就意味着某个变量会被多次定义,编译链接时不出错才怪呢!
此帖出自stm32/stm8论坛
 
 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

6
 
LS说得对,永远不要在.h文件中定义变量!
不过可以想UCOS那样在.h文件中定义全局变量
在.h文件中的全部登记变量用OS_EXT定义
#ifdef   OS_GLOBALS
#define  OS_EXT
#else
#define  OS_EXT  extern
#end
然后在其中任意一个引用的.c文件最前面中定义
#define  OS_GLOBALS
此帖出自stm32/stm8论坛
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

7
 
楼上这种做法有什么好处?
好像麻烦了更
此帖出自stm32/stm8论坛
 
 
 

回复

82

帖子

0

TA的资源

一粒金砂(中级)

8
 
                                 6楼的这段 是uc/os_II 的刚开始里有叙述,楼主的问题不知道是不是看了《C语言嵌入式系统编程修炼之道》产生的疑问?  确实这个 修炼之道 讲的很有道理,当楼主写个程序测试后,应该会 理解。
此帖出自stm32/stm8论坛
 
 
 

回复

65

帖子

0

TA的资源

一粒金砂(初级)

9
 


先谢谢楼上几位。是的,在《嵌入式c精华》。就如6楼说的,在.h文件里加入
#ifndef _MAIN_H_
#define _MAIN_H_
.......//在这里定义变量
#endif
以上这段是防止变量被重复定义,然后可以在不同的.c文件里引用该.h文件了。
这么做,并没有出错。如果这种使用方法是可以的话,为什么“永远不在在.h文件里定义变量”呢?
此帖出自stm32/stm8论坛
 
 
 

回复

90

帖子

0

TA的资源

一粒金砂(初级)

10
 
9楼:
加入
#ifndef _MAIN_H_
#define _MAIN_H_
.......//在这里定义变量
#endif
这个貌似只能防止某一个C文件重复包含该头文件引起的变量重定义,却没法防止两个C文件同时包含该头文件引起的重定义,就是说,如果一个C文件#include<main.h>了两次,编译不会报错,但是两个C文件都#include<main.h>就要报错了,变量重复定义。
而且“永远不在在.h文件里定义变量”这个并不绝对,像六楼的UCOS的那种写法就是在h文件中定义变量,只要在一个C文件中定义OS_GLOBALS,其它的C文件不定义,所有的C文件就都可以包含同一个h文件了。
此帖出自stm32/stm8论坛
 
 
 

回复

59

帖子

0

TA的资源

一粒金砂(初级)

11
 


先谢谢楼上。
6楼提到的UCOS的那种写法很好,(写错了一个地方,结尾不是#end,而是#endif)因为具有大量的变量时候,容易造成声明的头文件和变量定义的cpp文件中变量的不一致,该方法可以避免这样的情况。

“两个C文件都#include<main.h>就要报错了,变量重复定义”
这个在我的程序里并没有报错,程序运行也暂时正常。原因是什么呢?
我用vc60写了一个测试程序,当保存为一个main.c,一个test.c,一个global.h,编译没错,输出结果正常;
当保存为cpp格式,build时报错:
test.obj : error LNK2005: "int c" (?c@@3HA) already defined in main.obj
这个就是说重复定义了。
说明这种对重定义的支持是依据编译器的,c++标准下不允许这样做,c标准下似乎没问题?由于我一直是用c,
所以在我的程序里都“暂时”都很正常,究竟这么做会不会导致一些我未发现的错误呢?会不会c下的编译器会检测到第一个用到.h里的变量时候分配一个存储空间,后面(不管是不是多个c文件)用到的就不再分配了?
此帖出自stm32/stm8论坛
 
 
 

回复

70

帖子

0

TA的资源

一粒金砂(初级)

12
 
“我用vc60写了一个测试程序,当保存为一个main.c,一个test.c,一个global.h,编译没错”
楼上说的这种情况不具备普遍性,即使是C编译器。可以试试keil和IAR。都会报错,变量重定义。
此帖出自stm32/stm8论坛
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

13
 
                                 是的。所以这个方法不被鼓励,换到不同的编译环境下就会有问题了。我要好好修一修我的不良习惯了。。。。
此帖出自stm32/stm8论坛
 
 
 

回复

63

帖子

0

TA的资源

一粒金砂(初级)

14
 


这个问题,说说老x的做法:
  1. #ifndef __OSD_MAIN_H__
  2. #define __OSD_MAIN_H__

  3. #ifndef __OSD_MAIN_C__
  4.         //  XWJ_OSD  公用函数
  5.         /********************************************************/
  6.         extern void OSD_Init(void);                // OSD_ 初始化
  7.         extern void OSD_Cls(void);                // 清屏
  8.            ....
  9.         extern unsigned char xdata *SramAdr;
  10. #else
  11.         //  XWJ_OSD  公用函数
  12.         /********************************************************/
  13.         void OSD_Init(void);                        // OSD_ 初始化
  14.         void OSD_Cls(void);                        // 清屏
  15.            ....
  16.         unsigned char xdata *SramAdr;
  17. #endif

  18. #endif
复制代码
解释说明如下:
1、每个文件都有对应该文件名的标识定义:——这是为了避免多次重复包含这个头文件时出错,有了它就不管怎么重复引用这个头文件都没问题了。
#ifndef __OSD_MAIN_H__
#define __OSD_MAIN_H__
....
#endif

2、然后判断对应C文件的标识,没有定义__OSD_MAIN_C__的话则是外部引用,否则为真正的本地引用和变量声明——这样的话,在osd_main.c文件中先#define __OSD_MAIN_C__,然后再#include "osd_main.h",就可以确保只有唯一的一处会分配变量了,而别的程序中不定义#define __OSD_MAIN_C__,而只有#include "osd_main.h",所以执行的全都是#ifndef __OSD_MAIN_C__       ~    #else 之间的外部引用
  1. #ifndef __OSD_MAIN_C__
  2.         extern void OSD_Init(void);                // OSD_ 初
  3.         extern unsigned char xdata *SramAdr;
  4. ....
  5. #else
  6.         void OSD_Init(void);                        // OSD_ 初
  7.         unsigned char xdata *SramAdr;
  8. #endif
复制代码
注意:
在osd_main.c文件中这样写:
#define __OSD_MAIN_C__
#include "osd_main.h"
程序实体....

而在别的文件中却是这样写:
#include "osd_main.h"
程序实体....


修改:整理下格式
此帖出自stm32/stm8论坛
 
 
 

回复

60

帖子

0

TA的资源

一粒金砂(初级)

15
 
其实,不管怎样做,都要有个统一的风格和规范,然后所以的程序都照着这样子套就可以了。

可千万不要这里这样做,哪里那样做哦~,那样的话当你想把你的不同模块放在一起用时,肯定就会打架啦
此帖出自stm32/stm8论坛
 
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

16
 
俺喜欢把所有变量放在一个“common.h”里面,便于管理。如下:

//--------------------------------------------------------
//避免重复定义
//--------------------------------------------------------
#ifdef  root
  #define EXT_  
#else
  #define EXT_  extern
#endif

//--------------------------------------------------------
//定义变量
//--------------------------------------------------------
EXT_ u16 X_AVR;                                                            //X轴加速度采样滤波值
EXT_ u16 Y_AVR;                                                            //Y轴加速度采样滤波值
……
……
此帖出自stm32/stm8论坛
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

17
 
老x的做法有点在于换个硬件、模块时,只要把.c文件加如工程并包含对应的.h文件即可,其他的不用任何变动即可调用模块的函数、存储器并且编译无误,既不会重复也不会浪费;

而你的做法,一旦工程变动则每次都要去“common.h”里面整理,时间稍微久一点根本不可能记住哪些用了,哪些不要用。
此帖出自stm32/stm8论坛
 
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

18
 
老x的做法有点在于换个硬件、模块时,只要把.c文件加如工程并包含对应的.h文件即可,其他的不用任何变动即可调用模块的函数、存储器并且编译无误,既不会重复也不会浪费;

而你的做法,一旦工程变动则每次都要去“c ...
如果是底层模块,具有通用性的,也是该这么做。呵呵。
此帖出自stm32/stm8论坛
 
 
 

回复

85

帖子

0

TA的资源

一粒金砂(初级)

19
 
类的 成员 与其 声明是分开的。  某些是公共而某些是私有的。
要引用这个类,一般是包括它的头文件 XXX.H (里面有这个类向外提供的方法或成员函数,还有公共成员)

这些是C++  的做法。 不过现在的C#,JAVA好像有点不一样。
此帖出自stm32/stm8论坛
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

20
 
                                 
此帖出自stm32/stm8论坛
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表