一个C++程序的开发需要经过以下的步骤:编辑、编译、连接、运行调试。再具体一些就是:源代码→预处理器→编译器→目标代码→链接器→可执行程序。
1、源代码:源程序是指未编译的按照一定的程序设计语言规范书写的文本文件。在C++中,存储源代码的文件.cpp文件。
2、预处理器:C预处理器是C/C++程序的宏预处理器(macro preprocessor),其主要功能是头文件的包含(including files)、宏替换(macro expansion)、条件编译(conditional compilation)、行控制(line contral)。
(1)源文件包含(including files)
文件包含指令将某个文件的内容插入到该#include处。
常见的文件包含格式:
A、#include <filename>:在标准编译器包含目录中查找filename文件;
B、#include "filename":现在当前源文件目录中查找,若未找到,再到标准目录中查找。
为了避免多重包含(double inclusion),#include命令常常被强制同#include guard或者#pragma once一起使用。
例如:
文件grandfather.h
struct foo { int menber; };
文件 father.h
#include "grandfather.h"
文件 child.c
#include "grandfather.h" #include "father.h"
此时,grandfather.h文件被包含两次,由于结构体foo被定义两次,将会造成编译错误。解决该问题的办法:
A、使用#include guards
将grandfather.h修改为:
#ifndef GRANDFATHER_H #define GRANDFATHER_H struct foo { int member; }; #endif /*GRANDFATHER_H*/
B、使用#pragma once
将grandfather.h修改为:
#pragma once struct foo { int member; };
(2)条件编译
由#if、#ifdef、#ifndef开始,然后0-n个#elif,接着0-1个#else,最后跟#endif。当#if、#ifdef、#ifndef后面的条件表达式为真时,对代码进行编译,其控制逻辑跟if-else语句一样。
例如:
#include <iostream> using namespace std; #define A 2 int main() { #ifdef A cout << "Yes" << endl; #else cout << "No" << endl; #endif }
程序的运行结果是“Yes”,当注释掉A的宏定义后,运行结果为"No"。
(3)宏定义
宏定义有两种类型:object-like和function-like,也就是我们常说的简单宏定义和带参数的宏定义。
A、简单的宏定义
#define <identifier> <replacement token list>
例如:
#define PI 3.1415
B、带参数的宏定义
#define <identifier>(<parameter list>) <replacement token list>
例如:
#define Squre(r) (3.14*r*r)
其他的预处理中还有行控制、用户自定义错误。
参考文献:
[1] http://en.wikipedia.org/wiki/C_preprocessor;
[2] http://www.th7.cn/Program/cp/201403/182079.shtml.