编译预处理
- 格式:ppt
- 大小:141.50 KB
- 文档页数:15


第十章 预处理命令
所谓编译预处理是指,在对源程序进行编译之前,先对源程序中的编译预处理命令进行处理;然后再将处理的结果,和源程序一起进行编译,以得到目标代码。
一、宏定义与符号常量
在C语言中,“宏”分为无参数的宏(简称无参宏)和有参数的宏(简称有参宏)两种。
无参宏定义
1.无参宏定义的一般格式
#define 标识符 字符串
其中:“define”为宏定义命令;“标识符”为所定义的宏名,通常用大写字母表示,以便于与变量区别;“字符串”可以是常数、表达式、格式串等。
2.使用宏定义的优点
(1)可提高源程序的可维护性
(2)可提高源程序的可移植性
(3)减少源程序中重复书写字符串的工作量
例9.1 输入圆的半径,求圆的周长、面积和球的体积。要求使用无参宏定义圆周率。
/*程序功能:输入圆的半径,求圆的周长、面积和球的体积。 */
#define PI 3.1415926 /*PI是宏名,3.1415926用来替换宏名的常数*/
void main()
{
float radius,length,area,volume;
printf("Input a radius: ");
scanf("%f",&radius);
length=2*PI*radius; /*引用无参宏求周长*/
area=PI*radius*radius; /*引用无参宏求面积*/
volume=PI*radius*radius*radius*3/4; /*引用无参宏求体积*/
printf("length=%.2f,area=%.2f,volume=%.2f\n", length, area, volume);
}
3.说明
(1)宏名一般用大写字母表示,以示与变量区别。但这并非是规定。
(2)宏定义不是C语句,所以不能在行尾加分号。否则,宏展开时,会将分号作为字符串的1个字符,用于替换宏名。
预编译#define #ifdef #endif用法
2010-08-05 10:08
最近在看Linux底层代码,发现好多代码里有#define #ifdef #endif,找了个介绍详细的文章,供大家参考:
#ifdef的用法
灵活使用#ifdef指示符,我们可以区隔一些与特定头文件、程序库和其他文件版本有关的代码。
代码举例:新建define.cpp文件
#include “iostream.h”
int main()
{
#ifdef DEBUG
cout<< “Beginning execution of main()”;
#endif
return 0;
}
运行结果为:Press any key
to continue
改写代码如下:
#include “iostream.h”
#define DEBUG
int main()
{
#ifdef DEBUG
cout<< “Beginning execution of main()”;
#endif
return 0;
}
运行结果为:Beginning execution of main()
Press any key to continue更一般的情况是,#define语句是包含在一个特定的头文件中。
比如,新建头文件head.h,在文件中加入代码:
#ifndef DEBUG
#define DEBUG
#endif
而在define.cpp源文件中,代码修改如下:
#include “iostream.h”
#include “head.h”
int main(){
#ifdef DEBUG cout<< “Beginning execution of main()”;
#endif
return 0;
预编译处理
【学习目标】
◇ 理解编译预处理的概念。
◇ 了解宏定义的概念,掌握简单宏定义和带参数的宏定义的格式和使用方法。
◇ 了解文件包含的概念,掌握文件包含的格式和使用方法。能在程序中合理使用#include预处理指令
◇ 了解条件编译的概念,掌握条件编译的三种格式及其使用方法。能在程序中合理使用#define, #if,
#ifndef, #else, #undef, #elif等指令。
【重点和难点】
重点:编译预处理的概念,简单的宏定义与文件包含指令的用法。
难点:带参宏定义,条件编译指令,会用条件指令解决文件的重复包含问题。
【学习方法指导】
本章的内容比较简单,严格说来,它也不算是C++语言的组成部分。但是,一般说来,任何程序都离不开预编译指令。特别是文件包含指令和条件编译指令,应把它们搞清楚。虽然可以用宏定义的方法定义常数,但推荐使用const语句定义常量。在编程中,如果我们能恰当地运用条件编译,就可以提高程序运行的效率。
【知识点】
宏定义;宏替换;简单的宏定义;带参数的宏定义;文件包含;条件编译
第一节 宏定义
我们用C++进行编程的时候,可以在源程序中包括一些编译命令,以告诉编译器对源程序如何进行编译。这些命令包括:宏定义、文件包含和条件编译,由于这些命令是在程序编译的时候被执行的,也就是说,在源程序编译以前,先处理这些编译命令,所以,我们也把它们称之为编译预处理,本章将对这方面的内容加以介绍。
实际上,编译预处理命令不能算是C++语言的一部分,但它扩展了C++程序设计的能力,合理地使用编译预处理功能,可以使得编写的程序便于阅读、修改、 移植和调试。
预处理命令共同的语法规则如下:
◇ 所有的预处理命令在程序中都是以"#"来引导 如"#include "stdio.h""。
◇ 每一条预处理命令必须单独占用一行,如"#include "stdio.h" #include " 是不允许的。
gcc编译过程的四个阶段
1. 预处理(Preprocessing):
预处理是编译过程的第一阶段。预处理器负责对原始源文件进行处理,主要完成以下几个任务:
-处理宏定义:预处理器会将源文件中的宏定义展开为相应的代码片段,并将其保存在一个临时文件中。
-处理条件编译指令:预处理器会根据条件编译指令的结果决定是否包含或排除一些代码片段。
- 处理#include指令:预处理器会将源文件中的#include指令所引用的其他文件插入到该指令所在的位置。
-移除注释:预处理器会删除源文件中的注释。
预处理后的文件成为扩展名为.i的中间文件,它包含了所有宏定义及展开后的代码。
编译是编译过程的第二阶段。编译器将预处理生成的中间文件进行词法分析、语法分析和语义分析,生成相应的汇编代码。主要过程如下:
- 词法分析器将预处理生成的中间文件分解为一个个的词法单元(Token)。
- 语法分析器根据词法单元组织成的语法结构,生成抽象语法树(Abstract Syntax Tree,AST)。
-语义分析器对抽象语法树进行语义检查,包括类型检查和语义错误检查,确保程序的语义正确。 编译器将生成的汇编代码保存为扩展名为.s的汇编文件。
3. 汇编(Assembling):
汇编是编译过程的第三阶段。汇编器(Assembler)将编译器生成的汇编代码翻译成机器码,并生成目标文件。具体过程如下:
- 汇编器将汇编代码中的每一条汇编指令翻译成对应的机器码,同时为每个标号(Label)生成对应的地址。
-汇编器进行符号解析,将代码中引用的变量和函数与目标文件中的符号表进行匹配,生成正确的指令和地址。
汇编器将目标文件保存为扩展名为.o的目标文件。
4. 链接(Linking):
链接是编译过程的最后阶段。链接器(Linker)将目标文件与其他必要的库文件进行合并,生成最终的可执行文件或动态链接库。主要过程如下:
-链接器将目标文件中的函数和变量引用与其他目标文件中的定义进行匹配,解析外部引用,生成相应的引用表。