编译预处理
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
var=LENGTH*2; var=LENGTH*2; #undef YES 如 if(x==YES) (80+40 *2; cout<<“correct!\n”; 引号中的内容与宏名相同的不置换 0 ) 宏展开:var= 80+40 *2; 宏展开:var= #define YES else if (x==NO) cout<<“error!\n”; max() 宏定义可嵌套,不能递归 cout<<“correct!\n”; YES新作用域 预处理展开后: PI 3.14159 例 #define if(x==1) {…….. cout<<“2*PI=”<<PI*2<<endl; 例 #defineelse if (x==0) } cout<<“error!\n”; MAX MAX+10 () 宏定义中使用必要的括号() 宏展开:cout<<“2*PI=”<<3.14159*2<<endl;
下图是一个多文件系统的开发过程
多文件结构
file1.cpp
预编译
file1.h
file2.cpp
预编译
file2.h
filen.cpp
预编译
filen.h
临时文件1
编译
临时文件2
编译
临时文件n
编译
file1.obj
file2.obj
filen.obj
连接 运行
.lib C++标准类库
Filename. exe
带参数宏定义
一般形式: #define 宏名(参数表) 宏体
不能加空格 例 #define S(a,b) a*b ……….. area=S(3,2); 宏展开: area=3*2; 宏展开:形参用实参换,其它字符保留 宏体及各形参外一般应加括号()
例 #define S (r) PI*r*r 例 #define POWER(x) x*x 相当于定义了不带参宏S,代表字符串“(r) PI*r*r” x=4; y=6; z=POWER(x+y); 宏展开:z=(x+y)*(x+y); 一般写成: #define POWER(x) ((x)*(x)) 宏展开: z=((x+y)*(x+y));
#include <iostream.h> #include <iomanip.h> #include "powers.h" #define MAX_POWER 10 void main() { int n; cout<<"number\t exp2\t exp3\t exp4\n"; cout<<"----\t----\t-----\t------\n"; for(n=1;n<=MAX_POWER;n++) cout<<setw(4)<<n<<setw(8)<<sqr(n) <<setw(8)<<cube(n)<<setw(8)<<quad(n)<<endl; }
#include “file2.cpp” B A file2.cpp file1.cpp file1.cpp A file2.cpp
被包含文件内容
源文件(*.cpp或*.c) 宏定义 头文件(*.h) 数据结构定义
file3.c
file2.c file1.c A
文件包含可嵌套
函数说明等
#include “file2.c” A
宏定义 文件包含 条件编译 #define #include #if--#else--#endif等
格式:
“#”开头 占单独书写行 语句尾不加分号 不是C/C++语言的组成部分
§宏定义
不带参数宏定义
宏体可缺省,表示宏名 定义过或取消宏体
一般形式: #define 宏名 [宏体] 功能:用指定标识符(宏名)代替字符序列(宏体)
C++程序开发过程
§条件编译指令
目的:当希望在不同条件下编译程序的不同部分, 这种情况就要使用条件编译指令。 实现 1 .用宏名作为编译的条件 2. 表达式的值作为编译条件 格式为: 格式为: #ifdef<宏名> #if <表达式> <程序段1> <程序段1> [#else [#else <程序段2>] <程序段2>] #endif #endif 其中程序段可以是程序也可以是编译预处理指令。可以通 过在该指令安排宏定义来控制编译不同的程序段。
如 #define YES 1 定义位置:任意(一般在函数外面) #define NO 0 作用域:从定义命令到文件结束 #define PI 3.1415926 例 #define YES #define OUT cout<<“Hello,World”; 1 #undef可终止宏名作用域 main() 例例 #undef WIDTH80 #define 格式: #define WIDTH…….. 宏名 80 { YES原作用域 (WIDTH+40) #define LENGTH WIDTH+40 #define LENGTH } 宏展开:预编译时,用宏体替换宏名---不作语法检查
编译预处理
编译预处理与多文件结构
重点
§ 编译预处理
编译器在对源程序进行编译之前,首先 要由预处理程序对程序文本进行预处理 主要的预处理指令
# include <文件名> #define 与 #undef 条件编译
§ 多文件结构
一个C++项目包含多个源文件
编译预处理
作用:对源程序编译之前做一些预处理,生成扩展 C/C++源程序 源程序 预处理 编译 种类
说明:程序员也可以把自己常用的符号常量、宏或 函数原型创建在头文件中,在编程序的时候,可以 包含在源程序文件中,减少源代码的书写
§多文件结构
思路:
一个大的程序如何处理?
在开发较大程序时,通常将其分解为多个源程序文件,每个 较小的程序用一个源程序文件建立,形成多文件结构模式。 程序经过编辑、编译、连接,成为一个完整的可执行程序。
#include “file3.c” C B file3.c
file1.c
file2.c
例 文件包含举例
/* powers.h */ #define sqr(x) ((x)*(x)) #define cube(x) ((x)*(x)*(x)) #define quad(x) ((x)*(x)*(x)*(x))
多文件结构的实现方式
多文件结构在VC中是通过工程*.dsp(project file ) 进行管理, 在工程中建立若干用户定义的头文件.h和源程序文件.cpp。 头文件中定义用户自定义的数据类型和类,所有的程序实现 则放在不同的源程序文件*.cpp中。
编译过程
编译时每个源程序文件单独编译,如果源程序文件中有编译 预处理指令,则首先经过编译预处理生成临时文件存放在内 存,之后对临时文件进行编译生成目标文件.obj,编译后临 时文件撤销。所有的目标文件经连接器连接最终生成一个完 整的可执行文件.exe。
常用的头文件 头文件名 iostream.h iomanip.h Math.h String.h 功能
Include命令可用于包含扩展 名为.h的头文件,这些头文 件中定义有符号常量、宏或 声明的函数原型
Alloc.h
Malloc.h Mem.h Conio.h
头文件中可以包括:用户构造的 数据类型(如枚举类型),外部 变量,外部函数、常量和内联定 义不宜放在头文件中。
§文件包含
<> 直接按标准目录搜索 功能:将另一个源文件嵌入到当前源文件中该点 “” 先在当前目录搜索,再搜索标准目录 处 可指定路径 一般形式: #include “文件名” 或 #include <文件名> 处理过程:预编译时,用被包含文件的内容取代 该预处理命令,再对“包含”后的文件作一个源 文件编译
<
>
带参的宏与函数区别
带参宏 处理时间 参数类型 处理过程 程序长度 运行速度
功能
函数
编译时
无类型问题
程序运行时
定义实参,形参类型 不分配内存 分配内存 简单的字符置换 先求实参值,再代入形参 不变 变长 不占运行时间
实现较简单的功能
调用和返回占时间
任意难度
在C++中往往将带参数的宏定义为内联函数(inline),内联 函数也是在编译前将出现函数名的地方用函数体替换 < >
例:在调试程序时常常要输出调试信息,而调试完后不需要 输出这些信息,则可以把输出调试信息的语句用条件编译指 令括起来。形式如下: #ifdef DEBUG cout<<″a=″<<a<<′\t′<<″x=″<<x<<endl; #endif 在程序调试期间,在该条件编译指令前增加宏定义: #define DEBUG 调试好后,删除DEBUG宏定义,将源程序重新编译一次。 条件编译指令包括:#if、#else、#ifdef、#ifndef、#endif、 #undef等。 #ifndef与#ifdef作用一样,只是选择的条件相反。 #undef指令用来取消#define指令所定义的符号,这样可以 根据需要打开和关闭符号。
例 用宏定义和函数实现同样的功能
#define MAX(x,y) (x)>(y)?(x):(y) ……. void main() { int a,b,c,d,t; ……. t=MAX(a+b,c+d); …… } 宏展开:t=(a+b)>(c+d)?(a+b):(c+d);
int max(int x,int y) { return(x>y?x:y); } void main() { int a,b,c,d,t; ……. t=max(a+b,c+d); ……… }
下图是一个多文件系统的开发过程
多文件结构
file1.cpp
预编译
file1.h
file2.cpp
预编译
file2.h
filen.cpp
预编译
filen.h
临时文件1
编译
临时文件2
编译
临时文件n
编译
file1.obj
file2.obj
filen.obj
连接 运行
.lib C++标准类库
Filename. exe
带参数宏定义
一般形式: #define 宏名(参数表) 宏体
不能加空格 例 #define S(a,b) a*b ……….. area=S(3,2); 宏展开: area=3*2; 宏展开:形参用实参换,其它字符保留 宏体及各形参外一般应加括号()
例 #define S (r) PI*r*r 例 #define POWER(x) x*x 相当于定义了不带参宏S,代表字符串“(r) PI*r*r” x=4; y=6; z=POWER(x+y); 宏展开:z=(x+y)*(x+y); 一般写成: #define POWER(x) ((x)*(x)) 宏展开: z=((x+y)*(x+y));
#include <iostream.h> #include <iomanip.h> #include "powers.h" #define MAX_POWER 10 void main() { int n; cout<<"number\t exp2\t exp3\t exp4\n"; cout<<"----\t----\t-----\t------\n"; for(n=1;n<=MAX_POWER;n++) cout<<setw(4)<<n<<setw(8)<<sqr(n) <<setw(8)<<cube(n)<<setw(8)<<quad(n)<<endl; }
#include “file2.cpp” B A file2.cpp file1.cpp file1.cpp A file2.cpp
被包含文件内容
源文件(*.cpp或*.c) 宏定义 头文件(*.h) 数据结构定义
file3.c
file2.c file1.c A
文件包含可嵌套
函数说明等
#include “file2.c” A
宏定义 文件包含 条件编译 #define #include #if--#else--#endif等
格式:
“#”开头 占单独书写行 语句尾不加分号 不是C/C++语言的组成部分
§宏定义
不带参数宏定义
宏体可缺省,表示宏名 定义过或取消宏体
一般形式: #define 宏名 [宏体] 功能:用指定标识符(宏名)代替字符序列(宏体)
C++程序开发过程
§条件编译指令
目的:当希望在不同条件下编译程序的不同部分, 这种情况就要使用条件编译指令。 实现 1 .用宏名作为编译的条件 2. 表达式的值作为编译条件 格式为: 格式为: #ifdef<宏名> #if <表达式> <程序段1> <程序段1> [#else [#else <程序段2>] <程序段2>] #endif #endif 其中程序段可以是程序也可以是编译预处理指令。可以通 过在该指令安排宏定义来控制编译不同的程序段。
如 #define YES 1 定义位置:任意(一般在函数外面) #define NO 0 作用域:从定义命令到文件结束 #define PI 3.1415926 例 #define YES #define OUT cout<<“Hello,World”; 1 #undef可终止宏名作用域 main() 例例 #undef WIDTH80 #define 格式: #define WIDTH…….. 宏名 80 { YES原作用域 (WIDTH+40) #define LENGTH WIDTH+40 #define LENGTH } 宏展开:预编译时,用宏体替换宏名---不作语法检查
编译预处理
编译预处理与多文件结构
重点
§ 编译预处理
编译器在对源程序进行编译之前,首先 要由预处理程序对程序文本进行预处理 主要的预处理指令
# include <文件名> #define 与 #undef 条件编译
§ 多文件结构
一个C++项目包含多个源文件
编译预处理
作用:对源程序编译之前做一些预处理,生成扩展 C/C++源程序 源程序 预处理 编译 种类
说明:程序员也可以把自己常用的符号常量、宏或 函数原型创建在头文件中,在编程序的时候,可以 包含在源程序文件中,减少源代码的书写
§多文件结构
思路:
一个大的程序如何处理?
在开发较大程序时,通常将其分解为多个源程序文件,每个 较小的程序用一个源程序文件建立,形成多文件结构模式。 程序经过编辑、编译、连接,成为一个完整的可执行程序。
#include “file3.c” C B file3.c
file1.c
file2.c
例 文件包含举例
/* powers.h */ #define sqr(x) ((x)*(x)) #define cube(x) ((x)*(x)*(x)) #define quad(x) ((x)*(x)*(x)*(x))
多文件结构的实现方式
多文件结构在VC中是通过工程*.dsp(project file ) 进行管理, 在工程中建立若干用户定义的头文件.h和源程序文件.cpp。 头文件中定义用户自定义的数据类型和类,所有的程序实现 则放在不同的源程序文件*.cpp中。
编译过程
编译时每个源程序文件单独编译,如果源程序文件中有编译 预处理指令,则首先经过编译预处理生成临时文件存放在内 存,之后对临时文件进行编译生成目标文件.obj,编译后临 时文件撤销。所有的目标文件经连接器连接最终生成一个完 整的可执行文件.exe。
常用的头文件 头文件名 iostream.h iomanip.h Math.h String.h 功能
Include命令可用于包含扩展 名为.h的头文件,这些头文 件中定义有符号常量、宏或 声明的函数原型
Alloc.h
Malloc.h Mem.h Conio.h
头文件中可以包括:用户构造的 数据类型(如枚举类型),外部 变量,外部函数、常量和内联定 义不宜放在头文件中。
§文件包含
<> 直接按标准目录搜索 功能:将另一个源文件嵌入到当前源文件中该点 “” 先在当前目录搜索,再搜索标准目录 处 可指定路径 一般形式: #include “文件名” 或 #include <文件名> 处理过程:预编译时,用被包含文件的内容取代 该预处理命令,再对“包含”后的文件作一个源 文件编译
<
>
带参的宏与函数区别
带参宏 处理时间 参数类型 处理过程 程序长度 运行速度
功能
函数
编译时
无类型问题
程序运行时
定义实参,形参类型 不分配内存 分配内存 简单的字符置换 先求实参值,再代入形参 不变 变长 不占运行时间
实现较简单的功能
调用和返回占时间
任意难度
在C++中往往将带参数的宏定义为内联函数(inline),内联 函数也是在编译前将出现函数名的地方用函数体替换 < >
例:在调试程序时常常要输出调试信息,而调试完后不需要 输出这些信息,则可以把输出调试信息的语句用条件编译指 令括起来。形式如下: #ifdef DEBUG cout<<″a=″<<a<<′\t′<<″x=″<<x<<endl; #endif 在程序调试期间,在该条件编译指令前增加宏定义: #define DEBUG 调试好后,删除DEBUG宏定义,将源程序重新编译一次。 条件编译指令包括:#if、#else、#ifdef、#ifndef、#endif、 #undef等。 #ifndef与#ifdef作用一样,只是选择的条件相反。 #undef指令用来取消#define指令所定义的符号,这样可以 根据需要打开和关闭符号。
例 用宏定义和函数实现同样的功能
#define MAX(x,y) (x)>(y)?(x):(y) ……. void main() { int a,b,c,d,t; ……. t=MAX(a+b,c+d); …… } 宏展开:t=(a+b)>(c+d)?(a+b):(c+d);
int max(int x,int y) { return(x>y?x:y); } void main() { int a,b,c,d,t; ……. t=max(a+b,c+d); ……… }