做c/c++编程的对#include指令都不会陌生,绝大多数也都知道如何使用,但我相信仍有人对此是一知半解,
- C:
- #include
-
- C++:
- #include
表示包含C/C++标准输入头文件。包含指令不仅仅限于.h头文件,可以包含任何编译器能识别的C/C++代码文件,包括.c,.hpp,.cpp,.hxx,.cxx等,甚至.txt,.abc等等都可以
preprocess
预处理:为方便编译器处理而设置的一种机制,包括一些常用预处理指令和语句,我们统称为预处理系统。
如#include #define #if...#else...#endif #pragma等
这些指令的实现是由编译器来决定的(implementation specified)
提到预处理指令,顺便说一下头文件防止重复包含的2种方法
- #ifndef _ABCDE_H
- #define _ABCDE_H
-
- /*
- 代码部分
- */
-
- #endif
在被包含过一次之后,宏_ABCDE_H已经有了,下次再碰到就会略过从#define _ABCDE_H开始到#endif之间的代码
还有一种特定编译器支持的指令:
能保证该文件(物理上的)只被编译一次,也能起到防止重复包含的作用
但这2种方式是有区别的:
1)Macro guard可移植性好,绝大多数编译器都支持,而且万一不小心拷贝了几分相同的代码也不会出问题,但你得确保这个宏名不会与其他的宏冲突,否则等编译器报出一大堆错误的时候你可能会觉得莫名其妙;
2)#pragma once指令简单,它能保证该文件(物理上的)只被编译一次,不用去费劲的想不同的宏名,但如果有几份该文件的拷贝,显然起不到作用。
declaration
声明:指将一个名称引入当前编译单元,或者重新声明一个前面已经声明过的名称,声明指定了如何解释一个名称和该名称具有的属性;
例如:
- int main(void)
- {
- // 声明了变量a,类型为int
- int a;
-
- // 声明了变量pa,类型为指向int型的指针类型
- int *pa;
- }
definition
定义:除了以下情况,声明就是定义
以上情况适用于C具有的特征,C++则完全适用,一般来说定义要为其对象分配或预留存储空间,而声明则不用。
translation unit
编译单元:一个源文件,.c .cpp等和它所包含的文件一起,在经过预处理之后形成一个源码文件,标准称之为translation unit(编译单元)包括一系列的声明和定义;一个program(程序)由一个或多个编译单元组成。编译器将各个翻译单元编译为目标代码(.obj),通过连接器(linker)将这些编译后的编译单元(即目标代码)连接成完整的指令序列(可执行文件、静态库、动态库等)。
one definition rule
一次定义规则:是指定义在所有进入连接的编译单元中只能有一次。
- example_a.h:
-
- void function();
-
-
- example_a.cpp:
-
- #include "example_a.h"
-
- void function()
- {}
只要是用符合标准的代码编写的文本文件,就可以使用#include来进行包含,包括.cpp .c等常见的源文件扩展名;
- example_b_1.b
-
- void function();
-
-
- example_b_1.cpp:
-
- #include "example_b_1.b"
- void function()
- {}
-
-
- example_b_2.b
-
- void function1();
- void function2();
-
-
- example_b_21.cpp:
-
- void function1()
- {}
-
-
- example_b_22.cpp:
-
- #include "example_b_1.b"
- #include "example_b_21.cpp"
- void function2()
- {}
上面的例子中,example_b_21.cpp仅被包含在xample_b_22.cpp中,不再被其他的文件包含,而且不加入工程中;
最新的C++标准库中的一切内容都被放在名字空间std中(名字空间中的内容对外是不可见的),但是带来了一个新问题,无数现有的C++代码都依赖于使用了多年的伪标准库中的功能,如声明在