两个问题: 1、头文件重复包含 2、头文件加了ifndef条件预处理指令为什么还会定义

第一个问题:编译时重定义

文件1.h

void fun1();
struct A  
{
    int a
    char b;
};

 

文件2.h

#include"1.h"        
struct B
{
  struct A;
  int a;
};
void fun2();

 

文件1.cpp

#include"1.h"
#include"stdio.h"
void fun1()
{
    printf("fun1 is called\n");
}

文件2.cpp

#include"2.h"
#include<stdio.h>
void fun2()
{
    printf("fun2 is called\n");
}

文件main.cpp

#include<stdio.h>
#include"1.h"
#include"2.h"
void main()
{
   fun1();   
   fun2();   
}

运行结果:

这个很容易解释:

因为在main.cpp中,首先包含了1.h,这是编译器就会展开1.h,发现在其中定义了结构体类型A(并不是定义变量);接着包含2.h,编译器就会展开2.h,发现2.h的第一句是#include<1.h>,这是编译器又再一次展开1.h,由此造成了结构体A的重定义。这个问题是由于在main.cpp这个文件同时包含了1.h和2.h引起的,注意是同一个文件同时包含。但是在不同CPP文件中不存在该问题,如2.cpp中包含了1.h,main.cpp也包含了1.h,但是不会出现以上问题。这就证明了源文件是单独编译的。这个问题解决非常方便,只需要加条件预处理命令即可:

//1.h

#ifndef _a1_H
#define _a1_H
void fun1();
struct A
{
int a;
char b;
};
#endif

  

  

//2.h

#include"1.h"
#ifndef _2_H
#define _2_H
struct B
{
struct A;
int a;
};
void fun2();

#endif

  

//1.cpp

#include"1.h"
#include"stdio.h"

void fun1()
{
printf("fun1 is called\n");
}

  

//2.cpp

#include"2.h"
#include<stdio.h>

void fun2()
{
printf("fun2 is called\n");
}

  

//main.cpp

#include<stdio.h>
#include"1.h"
#include"2.h"
void main()
{
fun1();
fun2();
}

  

运行结果:

  

  

第二个问题:链接时重定义

假如现在1.h中加一句话 int a;其他不变,会出现什么情况

文件1.h 

#ifndef _a1_H
#define _a1_H
void fun1();
int a;//加一句话
struct A
{
int a;
char b;
};
#endif

运行结果:

这里也出现了重定义,但是这里是链接时的重定义。分析:这里在编译时由于加了条件预处理命令,所以在编译不会报错,但是由1.cpp,2.cpp,main。cpp生成的三个1.obj,2.obj,main.obj,中都定义了a 变量,造成链接时出错。如果把int a 换成extern int a就不会出错,因为extern int a,只声明变量,不分配内存,c语言允许多次声明,但不允许多次定义,即使在一个文件中出现两个extern int a,程序也不会报错。(ps:定义的函数和变量默认都是extern的)

  

 

posted @ 2014-03-05 22:26  yexuannan  阅读(1855)  评论(0编辑  收藏  举报