.C与.H文件区别与联系
2013-01-18 16:44
176 查看
.C与.H网上有很多文章会解释它们之间的区别与联系,小弟曾经也很搞不清楚。现在经过了大半年的编程,现在已经逐渐清晰了。
现在,我从力求使读者从C语言的角度明白.C与.H的区别和联系。
.C与.H与模块化编程是紧密联系的,刚刚从单一文件突然转换到了多个模块/文件,一定很不适应。笔者是个比较啰嗦的人,没有耐心看的人就看黑体字吧。
下面我们边回顾边讲解两者的区别与联系。
第一,函数的调用问题
函数在使用前要先定义,不先定义的话,要先声明。不熟悉的先回去啃啃C语言书再回来看。笔者认为自己讲解一般已经比较啰嗦了。
例如有两个文件file1.c和file2.c
一般在一个工程项目中,.c和.h文件都是一一对应且重名的,那么就会有另外两个file1.h和file2.h.
至于怎么新建工程,.C和.H怎么放的问题,网上也有很多,先去好好看看再回来继续,笔者用的是keil4.
我们继续,假如在file1.c中定义一个函数
void function1(void)
{
;
}
如果file2.c想要调用这个函数怎么办?
由于我们这个函数不在file2.c中,通常我们会在调用之前加上
extern void function1(void); //作一个外部定义的函数声明,这样我们就可以合法调用了
并且一般都是没问题的。
那么问题来了
extern void function1(void);这句话我们放在哪里?
放在file2.c?放在file2.h?
不,一般我们习惯上都放在file1.h中。
为什么呢?
第一,我们可以看看C的库函数,如果我们的函数只是给别人用,不希望或者根本不允许给别人看到的话,我们的函数都会在.C文件里面定义,
然后在同名的.H的文件里面作外部定义函数声明,这时候.H文件就好像某些人说的.C文件的说明书一样,告诉别人这个.C文件的功能。
这样别人想调用这个函数时,只需#include" xxx.h"即可。例如上例中
我们在file2.h中添加
#include "include file1.h"
在file2.c中
#include "include file2.h"
在file1.h中
extern void function1(void);
这样我们的file2.c就可以调用我们的file1.c中的function1函数了
当然如果你不怕麻烦,喜欢将“extern void function1(void);”写在file2.c中,并且你的下一个file3.c....filen.c都要调用此函数的时候,你都一遍遍敲代码
甚至说你一次要调用的外部定义函数有好几个你都喜欢自己敲代码而不按上面的方法的话,那么我也不拦着你,不过且听我说
第一我们实际过程中,函数名字为了见名知意,一般都挺长的,好几个单词组成
第二你的工程最后会出现很多重复的声明。
所以我推荐你使用这个方法。那么总结下
.C与.H的区别联系第一条:
.H文件是同名.C放置其供[b]别的文件调用的函数声明的地方。[/b]
第二,外部变量问题
这一点,原因跟第一条一样,习惯上我们也把供外部文件调用的变量放到.H文件中,通常这些变量都是全局变量;
.C与.H的区别联系第二条:
.H文件是同名.C放置其供[b]别的文件调用的变量声明(全局变量)的地方。[/b]
第三,文件包含问题
大家想一下,通常我们一个.C文件要包含一个或多个.H文件,为什么我们不把他们都放置到同名的.H文件里,而.C文件只包含自己的.H呢?
这样既简洁,实际上也带来不少好处,下面会讲到。
比方说file1.C要使用file2.H,file3.H...fileN.H
那我们一般也都放在file1.H中
而file1.C也只包含file1.H
由于是main函数一般要包含大量的.H文件,我们可以新建个main.h
然后将大量的.H文件都放进main.h中,这样既美观简洁,也有很多好处,我们下面会将好处。
.C与.H的区别联系第三条:
.H文件是同名.C放置文件包含的地方。
第四条,宏定义
不罗嗦了,一般宏定义也是放到.H文件。
.C与.H的区别联系第四条:
.H文件是同名.C放置宏定义的地方。
综上:.C和.H文件的联系有四点:
(1).H文件是同名.C放置其供别的文件调用的函数声明的地方。
(2).H文件是同名.C放置其供[b]别的文件调用的变量声明(全局变量)的地方。[/b]
(3).H文件是同名.C放置文件包含的地方。
(4).H文件是同名.C放置宏定义的地方。
那么区别呢:
(1)以上四条都放置在.H而非.C文件中
(2).H文件不放置函数定义,变量定义,以及别的文件用不着的静态全局变量等。
另外,补充一点,大家都知道文件包含会出现嵌套的问题,
例如文件A包含B,B包含C,那么文件A包含C
那么C语言中#“inlcude”是怎么实现的呢,
无非就是将包含的文件的代码全部替换到 “include”这个位置来。
为了防止重复包含,重复声明,重复宏定义等一系列重复问题。
我们通常采用如下形式:
例如file1.h通常这么写
#ifndef file1_h
#define file1_h
#include"xxx.h"
....
#define XXX xxx
....
extern void function1(void);//....
.....
extern void a;//...
....
#endif
不明白的话好好回去看看C的书就知道了
虽然我们在写一个大的工程的时候,尽量避免各种嵌套包含,但是一般情况下还是会出现大量的A包含B、C,D包含A,E又包含D的问题
那么
#ifndef
#define
#endif
就可以防止出现各种重复的声明等等;
如果你还不明白
你可以想想看
如果你全部工程都写在一个文件里
你要调用一个函数,想先调用后定义
你先做了声明void function(void);
然后只管去用了,那么我问你你每次用这个函数之前(假使你定义函数在最最后)都会再重新声明一次吗?
显然不会。
我们用多个文件完成一个工程,最后编译器会将它们整合成一个文件,我们一般不关心它们按什么顺序融合在一起,
也就自然不关心什么时候文件包含被替换了,但是我们也不会允许重复的声明包含和宏定义吧?所以用上述三行语句就可以解决这个问题了。
记得笔者当初C菜得跟渣一样的时候,一直很纳闷为啥包含.H就能用同名的.C的函数变量了呢?
现在看看还是C语言学得太烂了。不过笔者也问过好些人,其中有人也回答笔者:“就是那么用的,只管用就行”
包括后来的为什么安装了中断函数就能实现中断了呢。想想有些人不大喜欢求甚解,希望我的这篇文章能帮助那些喜欢打破沙锅问到底的人。
现在,我从力求使读者从C语言的角度明白.C与.H的区别和联系。
.C与.H与模块化编程是紧密联系的,刚刚从单一文件突然转换到了多个模块/文件,一定很不适应。笔者是个比较啰嗦的人,没有耐心看的人就看黑体字吧。
下面我们边回顾边讲解两者的区别与联系。
第一,函数的调用问题
函数在使用前要先定义,不先定义的话,要先声明。不熟悉的先回去啃啃C语言书再回来看。笔者认为自己讲解一般已经比较啰嗦了。
例如有两个文件file1.c和file2.c
一般在一个工程项目中,.c和.h文件都是一一对应且重名的,那么就会有另外两个file1.h和file2.h.
至于怎么新建工程,.C和.H怎么放的问题,网上也有很多,先去好好看看再回来继续,笔者用的是keil4.
我们继续,假如在file1.c中定义一个函数
void function1(void)
{
;
}
如果file2.c想要调用这个函数怎么办?
由于我们这个函数不在file2.c中,通常我们会在调用之前加上
extern void function1(void); //作一个外部定义的函数声明,这样我们就可以合法调用了
并且一般都是没问题的。
那么问题来了
extern void function1(void);这句话我们放在哪里?
放在file2.c?放在file2.h?
不,一般我们习惯上都放在file1.h中。
为什么呢?
第一,我们可以看看C的库函数,如果我们的函数只是给别人用,不希望或者根本不允许给别人看到的话,我们的函数都会在.C文件里面定义,
然后在同名的.H的文件里面作外部定义函数声明,这时候.H文件就好像某些人说的.C文件的说明书一样,告诉别人这个.C文件的功能。
这样别人想调用这个函数时,只需#include" xxx.h"即可。例如上例中
我们在file2.h中添加
#include "include file1.h"
在file2.c中
#include "include file2.h"
在file1.h中
extern void function1(void);
这样我们的file2.c就可以调用我们的file1.c中的function1函数了
当然如果你不怕麻烦,喜欢将“extern void function1(void);”写在file2.c中,并且你的下一个file3.c....filen.c都要调用此函数的时候,你都一遍遍敲代码
甚至说你一次要调用的外部定义函数有好几个你都喜欢自己敲代码而不按上面的方法的话,那么我也不拦着你,不过且听我说
第一我们实际过程中,函数名字为了见名知意,一般都挺长的,好几个单词组成
第二你的工程最后会出现很多重复的声明。
所以我推荐你使用这个方法。那么总结下
.C与.H的区别联系第一条:
.H文件是同名.C放置其供[b]别的文件调用的函数声明的地方。[/b]
第二,外部变量问题
这一点,原因跟第一条一样,习惯上我们也把供外部文件调用的变量放到.H文件中,通常这些变量都是全局变量;
.C与.H的区别联系第二条:
.H文件是同名.C放置其供[b]别的文件调用的变量声明(全局变量)的地方。[/b]
第三,文件包含问题
大家想一下,通常我们一个.C文件要包含一个或多个.H文件,为什么我们不把他们都放置到同名的.H文件里,而.C文件只包含自己的.H呢?
这样既简洁,实际上也带来不少好处,下面会讲到。
比方说file1.C要使用file2.H,file3.H...fileN.H
那我们一般也都放在file1.H中
而file1.C也只包含file1.H
由于是main函数一般要包含大量的.H文件,我们可以新建个main.h
然后将大量的.H文件都放进main.h中,这样既美观简洁,也有很多好处,我们下面会将好处。
.C与.H的区别联系第三条:
.H文件是同名.C放置文件包含的地方。
第四条,宏定义
不罗嗦了,一般宏定义也是放到.H文件。
.C与.H的区别联系第四条:
.H文件是同名.C放置宏定义的地方。
综上:.C和.H文件的联系有四点:
(1).H文件是同名.C放置其供别的文件调用的函数声明的地方。
(2).H文件是同名.C放置其供[b]别的文件调用的变量声明(全局变量)的地方。[/b]
(3).H文件是同名.C放置文件包含的地方。
(4).H文件是同名.C放置宏定义的地方。
那么区别呢:
(1)以上四条都放置在.H而非.C文件中
(2).H文件不放置函数定义,变量定义,以及别的文件用不着的静态全局变量等。
另外,补充一点,大家都知道文件包含会出现嵌套的问题,
例如文件A包含B,B包含C,那么文件A包含C
那么C语言中#“inlcude”是怎么实现的呢,
无非就是将包含的文件的代码全部替换到 “include”这个位置来。
为了防止重复包含,重复声明,重复宏定义等一系列重复问题。
我们通常采用如下形式:
例如file1.h通常这么写
#ifndef file1_h
#define file1_h
#include"xxx.h"
....
#define XXX xxx
....
extern void function1(void);//....
.....
extern void a;//...
....
#endif
不明白的话好好回去看看C的书就知道了
虽然我们在写一个大的工程的时候,尽量避免各种嵌套包含,但是一般情况下还是会出现大量的A包含B、C,D包含A,E又包含D的问题
那么
#ifndef
#define
#endif
就可以防止出现各种重复的声明等等;
如果你还不明白
你可以想想看
如果你全部工程都写在一个文件里
你要调用一个函数,想先调用后定义
你先做了声明void function(void);
然后只管去用了,那么我问你你每次用这个函数之前(假使你定义函数在最最后)都会再重新声明一次吗?
显然不会。
我们用多个文件完成一个工程,最后编译器会将它们整合成一个文件,我们一般不关心它们按什么顺序融合在一起,
也就自然不关心什么时候文件包含被替换了,但是我们也不会允许重复的声明包含和宏定义吧?所以用上述三行语句就可以解决这个问题了。
记得笔者当初C菜得跟渣一样的时候,一直很纳闷为啥包含.H就能用同名的.C的函数变量了呢?
现在看看还是C语言学得太烂了。不过笔者也问过好些人,其中有人也回答笔者:“就是那么用的,只管用就行”
包括后来的为什么安装了中断函数就能实现中断了呢。想想有些人不大喜欢求甚解,希望我的这篇文章能帮助那些喜欢打破沙锅问到底的人。
相关文章推荐
- 两种解决头文件被重复包含方法的联系与区别
- 虚拟内存与内存映射文件区别与联系
- (转)虚拟内存与内存映射文件区别与联系
- linux的文件和目录的区别和联系
- extern与头文件(*.h)的区别和联系
- C++中头文件、源文件之间的区别与联系
- .c文件和.h文件的概念与联系
- Android ELF文件中.got .plt .rel.plt .rel.dyn节的区别和联系
- extern与头文件(*.h)的区别和联系
- 分享:C++中头文件、源文件之间的区别与联系
- h文件和.c文件的区别与联系
- 文件打开模式r,w,a,r+,w+,a+的区别和联系
- 文件(file)和流(stream)的联系和区别
- 文件系统与数据库系统的区别和联系
- 强制把系统缓存写入文件sync和fsync函数,, fflush和fsync的联系和区别
- 块储存、对象存储、文件存储的区别和联系
- extern与头文件(*.h)的区别和联系
- C++ 标准头文件与C头文件区别与联系以及C风格字符串
- 强制把系统缓存写入文件sync和fsync函数,, fflush和fsync的联系和区别
- extern与头文件(*.h)的区别和联系