不知道上篇的例子有没有朋友去试过,试过的朋友应该很疑惑,为什么会报错?
我们来编译几个文件看看头文件到底是如何导入的;
a.c
void hellow(){ printf("hellow"); }
a.h
#include "b.h"; void hellow();
b.c
void word(){ printf("word"); }
b.h
void word();
test.c
#inculde <stdio.h> #inculde "a.h" int main(){ hellow(); word(); }
接下来把test.c编译为预编译文件..gcc -E test.c -o
用记事本打开文件,前面代码先不管拉到最下方
可以看到我们写的代码..前面代码是什么呢 前面一大坨都是库文件<stdio.h>的代码,所以include导入文件可以理解为拷贝文件进来 往下看
# 1 "testA.h" 1 于是他把testA.h的所有代码拷贝进来了:
但是拷贝的时候又遇到testA.h内的 # 1 "testB.h" 1 于是把testB.h的所有代码也考进来就有了下面几句
# 1 "testB.h" 1
void word();
这时候testA还没拷贝完继续拷贝testA的第二行
void hellow(); 当include都拷贝完了才会开始编译main函数。
在看上一篇的问题A.h包含B.h,B.h又包含A.h。。仔细想想预编译时会怎么样?
预编译到A.h 发现有一行#include "B.h"于是去拷贝B.h,又发现B.h有一行#include"A.h"又去拷贝A.h,造成无限循环...
那么如何解决这种问题呢?
#ifndef name
#define name
头文件内容
#endif
ifndef 是"if not defined"的简写,是宏定义的一种,它是可以根据是否已经定义了一个变量来进行分支选择
define 定义一个宏 endif 则是终止if
以下是个人对于头文件的一些理解和测试结果
1.当头文件引用自身或者相互引用时会出现死循环 提示循环过于深入
2.当A,B都包含C时编译可以通过 但预编译状态下可看到 C文件出现了两份 程序不会因此不能运行 但拖慢了程序的加载
3.当A,B中拥有重名的方法 并在主函数调用时会出现编译错误(不调用则编译通过) 未明确定义
4.C程序预编译时根据头文件查找目标文件(*.o),所以目标文件重新编译并不影响它所依赖的文件
5.解决头文件导入重复或循环问题
#ifndef _test_h_
#define _test_h_
头文件内容
#endif
---------------------------------------------------------------------------------------------------------------------------------
头文件就说到这里..之前有提到宏定义 宏定义是什么呢
#define A=3; //这是定义一个宏有不少人认为这就是定义一个全局的常量,但是他与常量相似却又有所不同,他会把代码中所有A都替换成3但这个操作是在预处理阶段就进行了,
比如你在代码中写道 int sum=2+A; 那么预处理之后就变成了int sum=2+3;
而定义常量const a=3;则是由编译器进行处理和分配空间
这里顺便提一下宏定义函数 我们写个例子
#include <stdio.h> #define SUM( a, b) (a*b) int main(){ int a=5; int b=6; int result=SUM(a+b,b+a); printf("%d\n",result); }
大胆的猜猜看输出结果是什么?
复制代码编译一次,结果是不是与想象中有所不同呢?
如果感到困惑请把它编译成预编译文件
仔细找找...宏定义函数是不是消失了? 是的 他用代码块替换掉了所有调用它的函数..这是宏定义函数比较有趣的一个地方
既然知道了原因,那么解决方式就一目了然了
#define SUM( a, b) ((a)*(b))这样编译输出的值就是你所期望的了