大型工程代码如何防止头文件被重复包含
如以下代码:
//vs 2012 : test.c
#include <stdio.h>
#include "test.h"
extern i;
extern void test1();
extern void test2();
int main()
{
test1();
printf("ok/n");
test2();
printf("%d/n",i);
return 0;
}
//vs 2012 : test.h
#ifndef _TEST_H_
#define _TEST_H_
char add1[] = "www.shellbox.cn/n";
char add2[] = "www.scriptbox.cn/n";
int i = 10;
void test1();
void test2();
#endif
//vs 2012 : test1.c
--
#include <stdio.h>
#include "test.h"
extern char add1[];
void test1()
{
printf(add1);
}
//vs 2012 : test2.c
#include<stdio.h>
#include "test.h"
extern char add2[];
extern i;
void test2()
{
printf(add2);
for (; i > 0; i--)
printf("%d-", i);
}
错误分析:
由于工程中的每个.c文件都是独立的解释的,即使头文件有
#ifndef _TEST_H_ #define _TEST_H_ .... #enfif
在其他文件中只要包含了test.h就会独立的解释,然后每个.c文件生成独立的标示符。在编译器链接时,就会将工程中所有的符号整合在一起,由于文件中有重名变量,于是就出现了重复定义的错误。
解决方法:
在.c文件中定义变量,然后再建一个头文件(.h文件),在所有的变量声明前加上extern,注意这里不要对变量进行的初始化。然后在其他需要使用全局变量的.c文件中包含.h文件。编译器会为.c生成目标文件,然后链接时,如果该.c文件使用了全局变量,链接器就会链接到定义变量的.c文件 。
//vs 2012 : test.h
//-------------------------------
#ifndef _TEST_H_
#define _TEST_H_
extern int i;
extern char add1[];
extern char add2[];
void test1();
void test2();
#endif
//vs 2012 : test.c
//-------------------------------
#include <stdio.h>
#include "test.h"
int i = 10;
char add1[] = "www.shellbox.cn/n";
char add2[] = "www.scriptbox.cn/n";
extern void test1();
extern void test2();
int main()
{
test1();
printf("ok/n");
test2();
printf("%d/n",i);
return 0;
}
//vs 2012 : test1.c
//-------------------------------
#include <stdio.h>
#include "test.h"
extern char add1[];
void test1()
{
printf(add1);
}
//vs 2012 : test2.c
//-------------------------------
#include <stdio.h>
#include "test.h"
extern char add2[];
extern int i;
void test2()
{
printf(add2);
for (; i > 0;i--)
printf("%d-",i);
}
问题扩展: 变量的声明有两种情况:
(1) 一种是需要建立存储空间的(定义、声明)。例如:int a在声明的时候就已经建立了存储空间。
(2) 另一种是不需要建立存储空间的(声明)。例如:extern int a其中变量a是在别的文件中定义的。
前者是"定义性声明(defining declaration)"或者称为"定义(definition)",而后者是"引用性声明(referncingdeclaration)"。从广义的角度来讲声明中包含着定义,但是并非所有的声明都是定义,例如:int
a它既是声明,同时又是定义。然而对于extern a来讲它只是声明不是定义。一般的情况下我们常常这样叙述,把建立空间的声明称之为"定义",而把不需要建立存储空间称之为"声明"。很明显我们在这里指的声明是范围比较窄的,也就是说非定义性质的声明。