C语言头文件的看法
2013-11-26 16:58
127 查看
1 术语
1.1 定义与声明
定义:建立存储空间。声明:不需要建立存储空间,仅仅是为了扩展该变量的作用范围而作的“声明”。
定义只能有一次,但声明可以很多。如int Num为定义,而extern Num或extern int Num则为声明。
1.2 变量的分类
l 作用域来分:局部变量与全局变量
l 生存期来分:静态存储方式(分配固定的存储空间)与动态存储方式(根据需要进行动态的分配),具体有4种:自动的auto,静态的static,寄存器的register,外部的extern。
n auto变量如果没有特别声明是static,则默认的变量都是auto
n static 用static声明局部变量:在函数调用结束后其值不消失,而保留原值,即其占用的存储单元不释放。(在编译时赋初值,即只赋初值一次,在程序运行时它已有初值)(虽然静态局部变量在函数调用结束后仍然存在,但其他函数是不能引用它的)
n 用static声明外部变量 变量只限于本文件引用,而不能被其他文件引用
1.3 内部函数与外部函数
内部函数又称静态函数:只能被本文件中其他函数所调用。定义内部函数时,在前面添加static。
外部函数:定义时添加关键字extern,在定义时省略extern,则隐含为外部函数。在需要调用此函数的文件中,用extern对函数作声明,表示该函数是在其他文件中定义的外部函数。
1.4 作用域
2 编译器的工作过程
简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程:
1.预处理阶段
2.词法与语法分析阶段
3.编译阶段,首先编译成纯汇编语句,再将之汇编成跟CPU相关的二进制码,生成各个目标文件 (.obj文件)
4.连接阶段,将各个目标文件中的各段代码进行绝对地址定位,生成跟特定平台相关的可执行文件,当然,最后还可以用objcopy生成纯二进制码,也就是去掉了文件格式信息。(生成.exe文件)
编译器在编译时是以C文件为单位进行的,也就是说如果你的项目中一个C文件都没有,那么你的项目将无法编译,连接器是以目标文件为单位,它将一个或多个目标文件进行函数与变量的重定位,生成最终的可执行文件,在PC上的程序开发,一般都有一个main函数,这是各个编译器的约定,当然,你如果自己写连接器脚本的话,可以不用main函数作为程序入口!
(main .c文件 目标文件 可执行文件)
2.1 头文件如何来关联源文件?
这个问题实际上是说,已知头文件"a.h"声明了一系列函数(仅有函数原型,没有函数实现),"b.cpp"中实现了这些函数,那么如果我想在"c.cpp"中使用"a.h"中声明的这些在"b.cpp"中实现的函数,通常都是在"c.cpp"中使用#include
"a.h",那么c.cpp是怎样找到b.cpp中的实现呢?
其实.cpp和.h文件名称没有任何直接关系,很多编译器都可以接受其他扩展名。
谭浩强老师的《C程序设计》一书中提到,编译器预处理时,要对#include命令进行"文件包含处理":将headfile.h的全部内容复制到#include
"headfile.h"处。这也正说明了,为什么很多编译器并不care到底这个文件的后缀名是什么----因为#include预处理就是完成了一个"复制并插入代码"的工作。
程序编译的时候,并不会去找b.cpp文件中的函数实现,只有在link的时候才进行这个工作。我们在b.cpp或c.cpp中用#include "a.h"实际上是引入相关声明,使得编译可以通过,程序并不关心实现是在哪里,是怎么实现的。源文件编译后成生了目标文件(.o或.obj文件),目标文件中,这些函数和变量就视作一个个符号。在link的时候,需要在makefile里面说明需要连接哪个.o或.obj文件(在这里是b.cpp生成的.o或.obj文件),此时,连接器会去这个.o或.obj文件中找在b.cpp中实现的函数,再把他们build到makefile中指定的那个可以执行文件中。
3 头文件的作用
l 头文件可以定义所用的函数列表,方便查阅你可以调用的函数;
l 头文件可以定义很多宏定义,就是一些全局静态变量的定义,在这样的情况下,只要修改头文件的内容,程序就可以做相应的修改,不用亲自跑到繁琐的代码内去搜索。
l 头文件只是声明,不占内存空间,要知道其执行过程,要看你头文件所申明的函数是在哪个.c文件里定义的,才知道。
l 头文件并不是C自带的,可以不用。
l 调用了头文件,就等于赋予了调用某些函数的权限,如果你要算一个数的N次方,就要调用Pow()函数,而这个函数是定义在math.c里面的,要用这个函数,就必需调用math.h这个头文件。
4 头文件的一般规则
a.宏定义(预处理#define);
b.结构、联合和枚举声明;
c.typedef声明;(typedef long doubleREAL;)
d.外部函数声明;
e.全局变量声明;
5 实际应用
l 定义宏常量或宏公式的时候,一定要加圆括号
l 头文件只声明不定义
l C语言中一个人为的规范:在.h文件中声明的函数,如果在其对应的.c文件中有定义,那么我们在声明这个函数时,不使用extern修饰符, 如果反之,则必须显示使用extern修饰符(即在不同的.h文件中,声明该函数,要添加extern).
可以用extern Num,而不是非要extern char Num。
l 不能把实际的代码(如函数体)或全局变量定义(即定义和初始化实例)放入头文件中。
l 不要试图用#include把你的源文件“链接”成一个整体。#include是用来引入头文件而不是.c文件的。
l 如果定义或声明为一个源文件私有则最好留在该文件中。(作用域限于单文件的私有函数和变量应该声明为static。)
l 当声明或定义需要在多个文件中共享时,把他们放入一个头文件中尤其重要。不要在两个或多个源文件的顶部重复声明或定义宏。应该把它们放入一个头文件中,然后在需要的时候用#include包含进来。这样做的原因并不仅仅是减少打字输入——这样可以保证在声明或定义变化的时候,只需要修改一处即可将结果一致地传播到各个源文件。(特别是,永远不要把外部函数原型放到.c文件中。参见2.)
l 当希望在多个源文件中共享变量或函数时,需要确保定义和声明的一致性。最好的安排是在某个相关的.c文件中定义,然后再头.h文件中进行外部声明,在需要使用的时候,只要包含对应的头文件即可。定义变量的.c文件也应该包含该头文件,以便编译器检查定义的和声明的一致性。
l 定义一个Globel_Var.C文件来放全局变量,然后在与之相对应的Globel_Var.H文件中来声明全局变量
l 防止被重复包含。
使用下面的宏防止一个头文件被重复包含。
#ifndef MY_INCLUDE_H
#define MY_INCLUDE_H
<头文件内容>
#endif
l 说明性头文件
还有一种头文件,说明性头文件,这种头文件不需要有一个对应的代码文件,在这种文件里大多包含了大量的宏定义,没有暴露的数据变量和函数。这些文件给出以下建议:
1,包含一些需要的概念性的东西.
2,命名方式,定义的功能.h
3,不包含任何其他的头文件.
4,不定义任何类型.
5,不包含任何数据和函数声明.
6 引用
/article/8605492.html
C语言头文件的使用
/article/9081392.html
C语言的变量作用域及头文件
/article/6025203.html
C语言头文件的作用
1.1 定义与声明
定义:建立存储空间。声明:不需要建立存储空间,仅仅是为了扩展该变量的作用范围而作的“声明”。
定义只能有一次,但声明可以很多。如int Num为定义,而extern Num或extern int Num则为声明。
1.2 变量的分类
l 作用域来分:局部变量与全局变量
l 生存期来分:静态存储方式(分配固定的存储空间)与动态存储方式(根据需要进行动态的分配),具体有4种:自动的auto,静态的static,寄存器的register,外部的extern。
n auto变量如果没有特别声明是static,则默认的变量都是auto
n static 用static声明局部变量:在函数调用结束后其值不消失,而保留原值,即其占用的存储单元不释放。(在编译时赋初值,即只赋初值一次,在程序运行时它已有初值)(虽然静态局部变量在函数调用结束后仍然存在,但其他函数是不能引用它的)
n 用static声明外部变量 变量只限于本文件引用,而不能被其他文件引用
1.3 内部函数与外部函数
内部函数又称静态函数:只能被本文件中其他函数所调用。定义内部函数时,在前面添加static。
外部函数:定义时添加关键字extern,在定义时省略extern,则隐含为外部函数。在需要调用此函数的文件中,用extern对函数作声明,表示该函数是在其他文件中定义的外部函数。
1.4 作用域
2 编译器的工作过程
简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程:
1.预处理阶段
2.词法与语法分析阶段
3.编译阶段,首先编译成纯汇编语句,再将之汇编成跟CPU相关的二进制码,生成各个目标文件 (.obj文件)
4.连接阶段,将各个目标文件中的各段代码进行绝对地址定位,生成跟特定平台相关的可执行文件,当然,最后还可以用objcopy生成纯二进制码,也就是去掉了文件格式信息。(生成.exe文件)
编译器在编译时是以C文件为单位进行的,也就是说如果你的项目中一个C文件都没有,那么你的项目将无法编译,连接器是以目标文件为单位,它将一个或多个目标文件进行函数与变量的重定位,生成最终的可执行文件,在PC上的程序开发,一般都有一个main函数,这是各个编译器的约定,当然,你如果自己写连接器脚本的话,可以不用main函数作为程序入口!
(main .c文件 目标文件 可执行文件)
2.1 头文件如何来关联源文件?
这个问题实际上是说,已知头文件"a.h"声明了一系列函数(仅有函数原型,没有函数实现),"b.cpp"中实现了这些函数,那么如果我想在"c.cpp"中使用"a.h"中声明的这些在"b.cpp"中实现的函数,通常都是在"c.cpp"中使用#include
"a.h",那么c.cpp是怎样找到b.cpp中的实现呢?
其实.cpp和.h文件名称没有任何直接关系,很多编译器都可以接受其他扩展名。
谭浩强老师的《C程序设计》一书中提到,编译器预处理时,要对#include命令进行"文件包含处理":将headfile.h的全部内容复制到#include
"headfile.h"处。这也正说明了,为什么很多编译器并不care到底这个文件的后缀名是什么----因为#include预处理就是完成了一个"复制并插入代码"的工作。
程序编译的时候,并不会去找b.cpp文件中的函数实现,只有在link的时候才进行这个工作。我们在b.cpp或c.cpp中用#include "a.h"实际上是引入相关声明,使得编译可以通过,程序并不关心实现是在哪里,是怎么实现的。源文件编译后成生了目标文件(.o或.obj文件),目标文件中,这些函数和变量就视作一个个符号。在link的时候,需要在makefile里面说明需要连接哪个.o或.obj文件(在这里是b.cpp生成的.o或.obj文件),此时,连接器会去这个.o或.obj文件中找在b.cpp中实现的函数,再把他们build到makefile中指定的那个可以执行文件中。
3 头文件的作用
l 头文件可以定义所用的函数列表,方便查阅你可以调用的函数;
l 头文件可以定义很多宏定义,就是一些全局静态变量的定义,在这样的情况下,只要修改头文件的内容,程序就可以做相应的修改,不用亲自跑到繁琐的代码内去搜索。
l 头文件只是声明,不占内存空间,要知道其执行过程,要看你头文件所申明的函数是在哪个.c文件里定义的,才知道。
l 头文件并不是C自带的,可以不用。
l 调用了头文件,就等于赋予了调用某些函数的权限,如果你要算一个数的N次方,就要调用Pow()函数,而这个函数是定义在math.c里面的,要用这个函数,就必需调用math.h这个头文件。
4 头文件的一般规则
a.宏定义(预处理#define);
b.结构、联合和枚举声明;
c.typedef声明;(typedef long doubleREAL;)
d.外部函数声明;
e.全局变量声明;
5 实际应用
l 定义宏常量或宏公式的时候,一定要加圆括号
l 头文件只声明不定义
l C语言中一个人为的规范:在.h文件中声明的函数,如果在其对应的.c文件中有定义,那么我们在声明这个函数时,不使用extern修饰符, 如果反之,则必须显示使用extern修饰符(即在不同的.h文件中,声明该函数,要添加extern).
可以用extern Num,而不是非要extern char Num。
l 不能把实际的代码(如函数体)或全局变量定义(即定义和初始化实例)放入头文件中。
l 不要试图用#include把你的源文件“链接”成一个整体。#include是用来引入头文件而不是.c文件的。
l 如果定义或声明为一个源文件私有则最好留在该文件中。(作用域限于单文件的私有函数和变量应该声明为static。)
l 当声明或定义需要在多个文件中共享时,把他们放入一个头文件中尤其重要。不要在两个或多个源文件的顶部重复声明或定义宏。应该把它们放入一个头文件中,然后在需要的时候用#include包含进来。这样做的原因并不仅仅是减少打字输入——这样可以保证在声明或定义变化的时候,只需要修改一处即可将结果一致地传播到各个源文件。(特别是,永远不要把外部函数原型放到.c文件中。参见2.)
l 当希望在多个源文件中共享变量或函数时,需要确保定义和声明的一致性。最好的安排是在某个相关的.c文件中定义,然后再头.h文件中进行外部声明,在需要使用的时候,只要包含对应的头文件即可。定义变量的.c文件也应该包含该头文件,以便编译器检查定义的和声明的一致性。
l 定义一个Globel_Var.C文件来放全局变量,然后在与之相对应的Globel_Var.H文件中来声明全局变量
l 防止被重复包含。
使用下面的宏防止一个头文件被重复包含。
#ifndef MY_INCLUDE_H
#define MY_INCLUDE_H
<头文件内容>
#endif
l 说明性头文件
还有一种头文件,说明性头文件,这种头文件不需要有一个对应的代码文件,在这种文件里大多包含了大量的宏定义,没有暴露的数据变量和函数。这些文件给出以下建议:
1,包含一些需要的概念性的东西.
2,命名方式,定义的功能.h
3,不包含任何其他的头文件.
4,不定义任何类型.
5,不包含任何数据和函数声明.
6 引用
/article/8605492.html
C语言头文件的使用
/article/9081392.html
C语言的变量作用域及头文件
/article/6025203.html
C语言头文件的作用
相关文章推荐
- C语言头文件的使用
- c语言头文件中函数是否加extern
- 定义自己的头文件(C语言)
- C语言编程入门之程序头文件的简要解析
- c语言头文件的作用以及写法
- C语言中的头文件
- 可扩散列--可扩散列头文件C语言
- [转]Linux C语言头文件搜索路径
- C语言一些有关字符串操作的库函数及其头文件
- C语言中的string头文件解析
- C语言中的头文件有多少种都有哪些?C函数库有哪些?
- 编写自己的C语言头文件
- c语言的头号标志性文件——头文件
- 工作记录--C语言头文件
- C语言与C++语言中的头文件
- 正则表达式实务之一:处理C语言头文件
- c语言:常用各种头文件的作用,如:#include &lt;stdlib.h&gt;
- 在C语言头文件中,#ifndef、#define、#endif的作用?
- C语言头文件、库文件的查找路径
- 配合Kruskal算法不相交集合头文件C语言