K.i.s.s.cross. 发表于 2013-5-20 20:04:01

头文件中的全局变量和条件编译及其作用



一、头文件
   头文件就是对用户的说明。函数,参数,共享变量,各种各样的接口的说明。提高程序的可读性。
   头文件对计算机而言没什么作用,它只是在预编译时在#include的地方展开一下,没别的意义了,其实头文件主要是给别人看的。我做过一个实验,将头文件的后缀改成xxx.txt,然后在引用该头文件的地方用#include"xxx.txt"编译,链接都很顺利的过去了,由此可知,头文件仅仅为阅读代码作用,没其它的作用了!
二、声明和定义[钱能:C++程序设计教程,C++ primer]
声明:声明语句声明某个名称。因为有了名称,在后续的语句中才可以使用。但若要能真正运行,还必须在适当地方提供该名称的定义。它是用于向程序表明变量的类型和名字。没分配存储空间。
定义:定义语句不但声明了名称,而且还给名称分配了存储空间,使之成为一个能够存放数据的实体。

什么时候是声明?什么时候是定义?如何判断?
这里先要讲到一个关键词:extern[谭浩强:C程序设计(第二版)]
用extern声明外部变量(即全局变量)
   外部变量是在函数的外部定义的,它的作用域为从变量的定义处开始,到本程序文件的结尾。在此作用域内,全局变量可以为程序中的各个函数所引用。编译时将外部变量分配在静态存储区。
   有时候需要用extern来声明外部变量,以扩展外部变量的作用域。
1)在一个文件内声明外部变量
void main()
{
    extern int a, b;
    printf("%d,%d\n",a,b);
}
int a=1, b=2;

如果main函数中的定义前不加extern,程序就会出错。因为外部变量定义在main之后。
2)在多文件的程序中声明外部变量
//file1.c
int a;
void main()
{
    ...
}
//file2.c
extern int a;
...


用extern声明外部变量时,类型名可以写也可以省略。如file2.c中的extern int a;可写为extern a;
extern只用作声明,而不用于定义。

变量声明
extern int a; //声明一个全局变量a
int a;      //定义一个全局变量a

变量可以多次声明,但只能定义一次。

函数声明对于函数也一样,也是定义和声明,定义的时候用extern,说明这个函数是可以被外部引用的,声明的时候用extern说明这是一个声明。 但由于函数的定义和声明是有区别的,定义函数要有函数体,声明函数没有函数体,所以函数定义和声明时都可以将extern省略掉,反正其他文件也是知道这个函数是在其他地方定义的,所以不加extern也行。两者如此不同,所以省略了extern也不会有问题。用一个例子来说明。
//hoo.h
int h; //定义
//goo.h
#include "hoo.h"
//foo.h
#include "hoo.h"
//goo.cpp 空
//hoo.cpp 空
//foo.cpp
#include "iostream.h"
#include "foo.h"
#include "goo.h"
#include "hoo.h"
void main()
{
    h = 0;
}


--------------------Configuration: Prove - Win32 Debug--------------------
Compiling...
foo.cpp
d:\mycode\vc++\prove\hoo.h(3) : error C2086: 'h' : redefinition
d:\mycode\vc++\prove\hoo.h(3) : error C2086: 'h' : redefinition
Error executing cl.exe.
Creating browse info file...

Prove.exe - 2 error(s), 0 warning(s)

这时会产生错误:redefinition,重复定义
因为在foo.cpp中
#include "foo.h" // 包含int h;
#include "goo.h" // 包含int h;
#include "hoo.h" // 包含int h;
这就说明:当一个头文件中定一个变量时,如果它被多次包含就会出现重复定义的错误。
所以:千万不要在头文件中定义变量解决上面的错误可以有两种方法。1)#ifndef ... #define ... #endif
将hoo.h修改如下:
#ifndef _HOO_H_
#define _HOO_H_
int h;
#endif
就不出现错误。
//2010.6.18上面说不会产生错误,是不对的。是因我在没有.cpp文件中加入hoo.h文件,如果多外.cpp文件包含hoo.h文件。比如,我在goo.cpp中加入语句:#include "hoo.h",则会出现如下错误:
goo.obj : error LNK2005: "int h" (?h@@3HA) already defined in foo.obj
//故在头文件中绝不能定义变量!
2)将定义改为声明。int h;改为 extern int h;这样,在其它文件中只要而且只能定义一次,就可以在各个文件中共享此变量。这就是说:变量可以多此声明,而只能定义一次。总结[网上]a.头文件(.h)中是对于该模块接口的声明,接口包括该模块提供给其它模块调用的外部函数及外部全局变量,对这些变量和函数都需在.h中文件中冠以extern关键字声明;(函数前可以省略)b.永远不要在.h文件中定义变量;(应该声明)c.如果要用其它模块定义的变量和函数,直接包含其头文件即可。(变量还需再次定义)



页: [1]
查看完整版本: 头文件中的全局变量和条件编译及其作用