C++源程序中以#开头、以换行符结尾的行称为预处理命令,不是语法成分,在编译前由预处理器执行,在目标程序中不含预处理指令对应的机器码。
文件包含命令#include的使用
文件包含,is指在一个C++源程序中通过#include命令将另一个文件(以.h、.c、.cpp为扩展名的文件)的全部内容包含进来。文件包含可以嵌套,但一条命令只能指定一个被包含文件。
头文件,is以.h(head)为扩展名的文件,包含宏定义、外部变量定义、结构类型定义等。
两种格式与区别
① #include<被包含文件名>
//到编译器指定的文件包含目录去查找被包含的文件。
② #include"被包含文件名"
//系统首先到当前目录下查找被包含文件,如果没有,再到系统指定的文件包含目录去查找。
//可以指定包含文件的路径,但字符串中药表示\,必须使用\\
//e.g:#include"c:\\...\\....h"
编译时预编译器将被包含文件的内容插入到源程序中#include命令的位置,以形成新的源程序。文件包含处理功能有助于减少重复劳动,当使用其他文件共用数据或函数时不必再重复定义。
宏定义分为两种:
不带参数的宏定义
#define 标识符 单词串
#define命令定义一个标识符来代表一个字符串(表达式),当在源程序中发现该标识符时,都用该字符串替换,形成新程序。
宏名 macro name,为标识符。
宏替换or宏代换 macro substitulition,为将程序中出现的与宏名相同的标识符替换为字符串的过程。
源程序与预编译处理的前后对比举例:
//源程序
#include<iostream>
using namespace std;
//把SIZE换成10
#define SIZE 10
//把TAB换成"\t"
#define TAB "\t"
int main(){
int a[SIZE];
for(int i=0;i<SIZE;i++){
cout<<a[i]<<TAB;
}
return 0;
}
//预编译处理(宏替换)后的源程序
#include<iostream>
using namespace std;
//宏替换内容
#define SIZE 10
#define TAB "\t"
int main(){
int a[10];//在预编译处理中 原本的SIZE替换成10
for(int i=0;i<10;i++){
cout<<a[i]<<"\t";//在预编译处理中 原本的TAB替换成"\t"
}
return 0;
}
注意
①最好把所有宏定义放在文件的最前面或另一个单独的文件中,不要分散多个位置。
②如果单词串太长,可以在行尾使用 \ 续行符。
③双引号包括在替代的内容之内。
④宏名的作用域是从#define定义之后直到宏定义所在文件结束,如果需要终止宏的作用域,使用命令:
#undef 标识符
⑤宏可以嵌套、重复定义,但不能递归定义:
正确嵌套定义:
#define A 1
#define B 2
#define C A+B
错误递归定义:
#define D D+10
⑥程序中的字符串常量(双引号中的字符),不做宏替换:
#define TT this is a test
cout<<"TT";
实际输出TT,而不是this is a test。
⑦定义宏时,如果宏是一个表达式,那么一定要将这个表达式 ( ) 括起来。
带参数的宏定义
#define 标识符(参数列表) 单词串
类函数宏,is宏定义成一个函数调用的形式。
源程序与预编译处理后的新源程序对比:
//源程序
//替换内容
#define MAX(x,y)((x)>(y)?(x):(y))
int main()
{
float a=1,b=2;
cout<<MAX(a,b)<<endl;
return 0;
}
//预编译处理(宏替换)后的源程序
//替换内容
#define MAX(x,y)(((x)>(y))?(x):(y))
int main()
{
float a=1,b=2;
//替换结果
cout<<MAX(((a)>(b))?(a):(b))<<endl;
return 0;
}
注意
①需要将整个宏内容括起来,还要将宏参数用 ( ) 括起来,否则可能引起非预期的结果。
②宏定义语句一般位于函数外,必须单独占一行。
③必须在#define命令最后按回车,否则引起编译错误。