程序的编译过程可以分为预处理、编译、汇编三部分,其中预处理是首先执行的过程,预处理过程扫描程序源代码,对其进行初步的转换,产生新的源代码提供给编译器。
预处理过程读入源代码之后,会检查代码里包含的预处理指令,完成诸如包含其他源文件、定义宏、根据条件决定编译时是否包含某些代码的工作。下面介绍一些C/C++中预编译的指令。
一 #指令预处理指令以#号开头,并且#号必须是该行除了任何空白字符外的第一个字符。#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。单纯一个#号表示空指令,没有任何作用。二 #include指令#include预处理指令的作用是在指令处展开被包含的文件。展开被包含的文件之后,在代码就可以正常地调用该文件中所声明的变量和函数。#include指令有两种使用方法#include <xxx.h>#include "xxx.h"第一种方法将待包含的头文件使用尖括号括起来,预处理程序会在系统默认目录或者括号内的路径查找,通常用于包含系统中自带的公共头文件。第二种方法将待包含的头文件使用双引号引起来,预处理程序会在程序源文件所在目录查找,如果未找到则去系统默认目录查找,通常用于包含程序作者编写的私有头文件。文件包含可以是多重的,也就是说一个被包含的文件中还可以包含其他文件。在大型的程序中可能会产生重复包含的问题,如#include "a.h"#include "b.h"一个程序包含了a.h和b.h两个头文件,但a.h和b.h可能同时又都包含了c.h,于是该程序就包含了两次c.h,这在一些场合下会导致程序的错误,可以通过下面的条件编译进行解决。三 #define、#undef指令#define指令定义了一个标识符及一个串,标识符称为宏名,源程序中宏名的每次出现都会用其定义的串进行替换,称为宏替换。#undef指令取消一个已定义的宏。宏一般使用大写字母定义,其可以出现在程序的任意地方。宏替换仅仅是以文本串代替宏标识符的过程,该过程很容易出现一些逻辑上的错误,需要仔细处理一些关于括号的问题。以下代码用宏定义了一个常量PI,但C++中建议使用const进行常量定义,因为宏替换并不会进行类型匹配之类的安全性检查。同时用宏定义了一个MAX函数,其好处是没有函数调用的额外开销,运行速度较快,但容易出错,而且大量的宏替换会增加代码的长度。- void test1()
- {
-
-
- cout << PI << endl; //3.14
- cout << MAX(2, 3) << endl; //3
-
- //cout << PI << endl; //编译出错
- }
另外还有两个特殊的运算符:
宏定义中的#运算符把跟在其后的参数转换成一个字符串称为字符串化运算符。宏定义中的##运算符把出现在##两侧的参数合并成一个符号。
- void test2()
- {
-
- cout << CAT(123) << endl;//ABC123
-
-
- cout << NUM(1, 2) << endl;//12
- cout << STR("Hello", "World") << endl;//HelloWorld
- }
这几个指令称为条件编译指令,可对程序源代码的各部分有选择地进行编译。 跟一般的if、else if、else语句类似,如果一个条件上的值为真,则编译它对应的代码,否则提过这些代码,测试下一个条件上的值是否为真。注意,作为条件的表达式是在编译时求值的,它必须仅含常量及已定义过的标识符,不可使用变量,也不可以含有操作符sizeof(sizeof也是编译时求值)。 命令#endif标识一个#if块的结束。
- void test3()
- {
-
-
-
- cout << "Option: 1" << endl;
-
- cout << "Option: 2" << endl; //选择这句
-
- cout << "Option: Illegal" << endl;
-
- }
- void test4()
- {
- cout << "Current File: " << __FILE__ << endl; //Current File: d:\test.cpp
- cout << "Current Line: " << __LINE__ << endl; //Current Line: 48
-
- cout << "Current File: " << __FILE__ << endl; //Current File: d:\wrongfile
- cout << "Current Line: " << __LINE__ << endl; //Current Line: 1001
- }
- void test5()
- {
-
-
- cout << "Option: 1" << endl;
-
- cout << "Option: 2" << endl;
-
-
-
- }
- void test6()
- {
-
-
- bool a = 5; //无警告信息
-
- bool b = 5; //warning C4305: 'initializing' : truncation from 'int' to 'bool'
- }
- <pre name= "code" class="cpp">#pragma data_seg("MyData")
- int value; //共享数据
-
该指令规定数据在内存中的对齐长度,具体可以参考这里。
-
- struct S{ char a; int b; };
- void test7(){ cout << sizeof(S) << endl; } //5
-