#include防范
在C和C++程式语言中,#include防范,有时被称作巨集防范,用于处理#include
指令时,可避免重复引入的问题。在标头档加入#include防范是一种让档案等幂的方法。
重复引入
以下的C语言程式展示了缺少#include防范时会出现的问题:
- 档案“grandfather.h”
struct foo {
int member;
};
- 档案“father.h”
#include "grandfather.h"
- 档案“child.c”
#include "grandfather.h"
#include "father.h"
此处child.c间接引入了两份grandfather.h标头档中的内容。明显可以看出,foo
结构被定义两次,因此会造成编译错误。
使用#include防范
- 档案“grandfather.h”
#ifndef GRANDPARENT_H
#define GRANDPARENT_H
struct foo {
int member;
};
#endif
- 档案“father.h”
#include "grandfather.h"
- 档案“child.c”
#include "grandfather.h"
#include "father.h"
此处grandfather.h第一次被引入时会定义巨集GRANDPARENT_H。当father.h再次引入grandfather.h时,#ifndef
测试失败,编译器会直接跳到#endif
的部分,也避免了第二次定义foo
结构。程式也就能够正常编译。
困难
为了让#include防范正确运作,每个防范都必须检验并且有条件地设定不同的前置处理巨集。因此,使用了#include防范的方案必须制订一致性的命名方法,并确定这个方法不会和其他的标头档或任何可见的全域变数冲突。
为了解决这个问题,许多C和C++程式开发工具提供非标准的指令#pragma once
。在标头档中加入这个指令,能够保证这个档案只会被引入一次。不过这个方法会被潜在性显著的困难阻挠,无论#include
指令是否在不同的地方,但实际上起源于相同的开头(举例,请参考符号连结)。同样的,因为#pragma once
不是一个标准的指令,它的语意在不同的程式开发工具中也许会有微妙的不同。