原创 51单片机C语言中.c文件和.h文件的关联

2011-9-17 17:25 5134 5 7 分类: MCU/ 嵌入式

1)h文件作用
1 方便开发:包含一些文件需要的共同的常量,结构,类型定义,函数,变量申明;
2 提供接口:对一个软件包来说可以提供一个给外界的接口(例如: stdio.h)。

2)h文件里应该有什么
    常量,结构,类型定义,函数,变量申明。

3)h文件不应该有什么
    变量定义, 函数定义。

4)extern问题
    对于变量需要extern;
    对于函数不需要因为函数的缺省状态是extern的.如果一个函数要改变为只在文件内可见,加static。

5)include包含问题
    虽然申明和类型定义可以重复,不过推荐使用条件编译。

#ifndef _FILENAME_H,

#define _FILENAME_H

……

#endif

6)应该在那儿包含h文件
    在需要的地方.比如某个提供接口的h文件仅仅被1.c文件需要,那么就在1.c文件里包含。                


编写的程序一般会有.H文件和相对应的.C文件,.H文件是声明所用,.C文件是其函数实现部分。在调用时只要包含.H文件即可,我们没有听说过#i nclude "delay.c"这类的程序,同时也不提倡使用这个形式。

   


extern void Delayms(unsigned int n);

#endif


在delay.c文件中:                 //函数实现部分

#i nclude <delay.h>

//for crystal 11.0592M

void Delayms(unsigned int n)

{

       unsigned int i,j;

       for(j=n;j>0;j--)

       for(i=112;i>0;i--);

}

 

在主程序main.c中

#i nclude <delay.h>                //在主程序包含.h文件,不能包含.c文件

……


上述方法仍然要求每建立一个工程就需要把对应的头文件复制到工程的文件夹里,这样看来仍然是比较麻烦的,这时还有另外一中方法就是将做好的头文件放在一个文件夹中,然后将这个文件夹整体拷贝到..KEIL\C51\INC\下面,以后若需要使用某个头文件,就如使用KEIL自带的头文件一样方便了,在主函数mani()之前有一句#i nclude 就可以在main()中使用其中的函数了。


参考资料:

1)h文件里变量(函数)申明用不用extern

http://www.unixresources.net/linux/clf/program/archive/00/00/33/65/336569.html

2).c文件和.h文件的概念与联系

http://www.vckbase.com/document/viewdoc/?id=1607

3)过马路,左右看

http://www.vckbase.com/document/viewdoc/?id=1606

4).c 和 .h文件的不同

http://hi.baidu.com/mfantastic/blog/item/d6fddd39793494f73a87ce0c.html

5)C51包含头文件方法

http://blog.ednchina.com/eleclike/52862/message.aspx

 

模块划分的"划"是规划的意思,意指怎样合理的将一个很大的软件划分为一系列功能独立的部分合作完成系统的需求。C语言作为一种结构化的程序设计语言,在模块的划分上主要依据功能(依功能进行划分在面向对象设计中成为一个错误,牛顿定律遇到了相对论),C语言模块化程序设计需理解如下概念:

    (1)模块即是一个.c文件和一个.h文件的结合,头文件(.h)中是对于该模块接口的声明;

    (2)某模块提供给其它模块调用的外部函数及数据需在.h中文件中冠以extern关键字声明;

    (3)模块内的函数和全局变量需在.c文件开头冠以static关键字声明;

    (4)永远不要在.h文件中定义变量!定义变量和声明变量的区别在于定义会产生内存分配的操作,是汇编阶段的概念;而声明则只是告诉包含该声明的模块在连接阶段从其它模块寻找外部函数和变量。如:



/*module1.h*/
int a = 5; /* 在模块1的.h文件中定义int a */
/*module1 .c*/
#include "module1.h" /* 在模块1中包含模块1的.h文件 */
/*module2 .c*/
#include "module1.h" /* 在模块2中包含模块1的.h文件 */
/*module3 .c*/
#include "module1.h" /* 在模块3中包含模块1的.h文件 */

  以上程序的结果是在模块1、2、3中都定义了整型变量a,a在不同的模块中对应不同的地址单元,这个世界上从来不需要这样的程序。正确的做法是:



/*module1.h*/
extern int a; /* 在模块1的.h文件中声明int a */
/*module1 .c*/
#include "module1.h" /* 在模块1中包含模块1的.h文件
*/int a = 5; /* 在模块1的.c文件中定义int a */
/*module2 .c*/
#include "module1.h" /* 在模块2中包含模块1的.h文件 */
/*module3 .c*/
#include "module1.h" /* 在模块3中包含模块1的.h文件 */

这样如果模块1、2、3操作a的话,对应的是同一片内存单元。
PARTNER CONTENT

文章评论2条评论)

登录后参与讨论

用户577271 2015-10-16 15:55

请问大神一个问题, 如果 一个变量 被A.c B.c .....很多个文件 用到。 那么请问这个变量应该在哪里 定义呢? 在main.c 中定义,然后在其余A.h B.h 中进行extern 声明吗? 那如果很多个呢???那不是很麻烦????

用户377235 2015-7-16 20:42

真是大神啊!讲得太好了!!!

用户1647523 2012-2-17 16:36

EDNChina编辑您好:我读了您的文章,终于明白了很多困惑的问题了,说实话,我自己也觉得这个博客真的与众不同,打开看着不想是自己的博客啊,广告有点多,不支持超链接,排版,很不方便。希望能尽快完善。

liangziusb_940932268 2011-12-24 14:28

尊敬的EDNCHINA编辑,你们的公开信也发表一个多月了,至今也不见有什么改进!这期间我也试着再写一些文章,但怎么就还得要“政治审查”呢,我等一个搞技术的工人,又不是什么政治家,用得着“政治审查”吗? 请给个答复,“政治审查”是怎么一回事?

用户278701 2011-12-20 09:49

搬家新浪,停止EDN更新。

用户116683 2011-12-15 12:40

之前的博客还会恢复吗?

walnutcy_696810119 2011-12-10 16:02

不会用BLOG了

用户271389 2011-11-29 10:33

蛋都碎了!第一篇博客精华,改版以后没了……

liangziusb_940932268 2011-11-25 11:14

刚写了一个USB3.0方面的技术性文章,怎么不能发表呢?提示含有什么“政治敏感兴东西,居然还需要政治审查”才能发表! 我晕,EDN这是怎么了,是不是在自残呀!看来我只能搬家了。

用户243959 2011-11-23 11:55

连E空间也没有了,操!
相关推荐阅读
用户1407079 2011-09-27 08:30
C语言嵌入式系统编程之软件架构篇
模块划分   模块划分的“划”是规划的意思,意指怎样合理的将一个很大的软件划分为一系列功能独立的部分合作完成系统的需求。C语言作为一种结构化的程序设计语言,在模块的划分上主要依据功能(依功能进行划分在...
用户1407079 2011-09-26 17:01
电子工程师必上的十大专业网站
在电子产业混,情报能力是相当重要的,具体体现在一要能及早全面地获得最新的设计资讯,二要能认识一些专家级的大虾,当有设计难题时,这些大虾可以伸出热情的手拉你一把,则对你的设计会帮助很大的。小可我在电子产...
用户1407079 2011-09-17 17:27
c语言中volatile关键字
volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。 用volatile关键字声明的变量i每一次被访问时,执行部件都会从i相应的内存单元中取出i的值。 没有...
用户1407079 2011-09-17 16:40
EMC的PCB设计技术
除了元器件的选择和电路设计之外,良好的印制电路板(PCB)设计在电磁兼容性中也是一个非常重要的因素。PCB EMC设计的关键,是尽可能减小回流面积,让回流路径按照设计的方向流动。最常见返回电流问题来自...
EE直播间
更多
我要评论
2
5
关闭 站长推荐上一条 /3 下一条