预处理指令编译
编译,编译程序读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,再由汇编程序转换为机器语言,并且按照操作系统对可执行文件格式的要求链接生成可执行程序。
如果用一张图来表示:
读取c源程序,对其中的伪指令(以#开头的指令)和特殊符号进行处理
[析] 伪指令主要包括以下四个方面
(1)宏定义指令,如#define Name TokenString,#undef等。对于前一个伪指令,预编译所要做的是将程序中的所有Name用TokenString替换,但作为字符串常量的Name则不被替换。对于后者,则将取消对某个宏的定义,使以后该串的'出现不再被替换。
(2)条件编译指令,如#ifdef,#ifndef,#else,#elif,#endif,等等。这些伪指令的引入使得程序员可以通过定义不同的宏来决定编译程序对哪些代码进行处理。预编译程序将根据有关的文件,将那些不必要的代码过滤掉
(3)头文件包含指令,如#include "FileName"或者#include 等。在头文件中一般用伪指令#define定义了大量的宏(最常见的是字符常量),同时包含有各种外部符号的声明。采用头文件的目的主要是为了使某些定义可以供多个不同的C源程序使用。因为在需要用到这些定义的C源程序中,只需加上一条#include语句即可,而不必再在此文件中将这些定义重复一遍。预编译程序将把头文件中的定义统统都加入到它所产生的输出文件中,以供编译程序对之进行处理。
包含到c源程序中的头文件可以是系统提供的,这些头文件一般被放在/usr/include目录下。在程序中#include它们要使用尖括号(<>)。另外开发人员也可以定义自己的头文件,这些文件一般与c源程序放在同一目录下,此时在#include中要用双引号("")。
(4)特殊符号,预编译程序可以识别一些特殊的符号。例如在源程序中出现的LINE标识将被解释为当前行号(十进制数),FILE则被解释为当前被编译的C源程序的名称。预编译程序对于在源程序中出现的这些串将用合适的值进行替换。
注意:
预编译程序所完成的基本上是对源程序的“替代”工作。经过此种替代,生成一个没有宏定义、没有条件编译指令、没有特殊符号的输出文件。这个文件的含义同没有经过预处理的源文件是相同的,但内容有所不同。下一步,此输出文件将作为编译程序的输出而被翻译成为机器指令。
㈡ 预编译的编译指令
预编译指令指示了在程序正式编译前就由编译器进行的操作,可以放在程序中的任何位置。常见的预编译指令有:
(1)#include 指令
该指令指示编译器将xxx.xxx文件的全部内容插入此处。若用<>括起文件则在系统的INCLUDE目录中寻找文件,若用 括起文件则在当前目录中寻找文件。一般来说,该文件是后缀名为h或cpp的头文件。
注意:<>不会在当前目录下搜索头文件,如果我们不用<>而用把头文件名扩起,其意义为在先在当前目录下搜索头文件,再在系统默认目录下搜索。
(2)#define指令
该指令有三种用法:
第一种是定义标识,标识有效范围为整个程序,形如#define XXX,常与#if配合使用;
第二种是定义常数,如#define max 100,则max代表100(这种情况下使用const定义常数更好,原因见注1);
第三种是定义函数,如#define get_max(a, b) ((a)>(b)?(a):(b)) 则以后使用get_max(x,y)就可以得到x和y中较大的数(这种方法存在一些弊病,见注2)。
第四种是定义宏函数,如#define GEN_FUN(type) type max_##type(type a,type b){return a>b?a:b;} ,使用时,用GEN_FUN(int),则此处预编译后就变成了 max_int(int a,int b){return a>b?a:b;},以后就可以使用max_int(x,y)就可以得到x和y中较大的数.比第三种,增加了类型的说明。
(3)#if、#else和#endif指令
这些指令一般这样配合使用:
#if defined(标识) //如果定义了标识
要执行的指令
#else
要执行的指令
#endif
在头文件中为了避免重复调用(比如说两个头文件互相包含对方),常采用这样的结构:
#if !(defined XXX) //XXX为一个在你的程序中唯一的标识符,
//每个头文件的标识符都不应相同。
//起标识符的常见方法是若头文件名为abc.h
//则标识为abc_h
#define XXX
真正的内容,如函数声明之类
#endif
注1:因为:const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误(边际效应)。
注2:例如get_max(a++, b)时,a++会被执行多少次取决于a和b的大小!所以建议还是用内联函数而不是这种方法提高速度。虽然有这样的弊病,但这种方法的确非常灵活,因为a和b可以是各种数据类型。
注3:可以查看网络的预处理命令,编排的比较简明。
㈢ C语言提供的预编译处理命令主要有哪三种
1.宏定义:用一个指定的标识符(即名字)来代表一个字符串,如:用PI代表3.1415926,#define PI 3.1415926
2.文件包含:指一个源文件可以将另外一个源文件的全部内容包含进来,#include<文件名>
3.条件编译:对一部分内容指定编译的条件,即满足一定的条件才编译,主要有:
(1)#ifdef标识符
程序段1
#eles
程序段2
#endif
(2)#ifndef标识符
程序段1
#eles
程序段2
#endif
(3))#if标识符
程序段1
#eles
程序段2
#endif
㈣ C语言“编译预处理命令”,是什么意思
您好,
宏定义
c程序提供的预处理功能之一。包括带参数的宏定义和不带参数的宏定义。具体是指用一个指定的标志符来进行简单的字符串替换或者进行阐述替换。形式为:
#define
标志符(参数表)
字符串
宏名
在上定义中的标志符被称为“宏名”。
宏展开
在c程序编译时将宏名替换成字符串的过程称为“宏展开”。
define
是对宏的定义:如定义了一个宏m,代表100.也就在下面的程序中只要是遇到变量m,它的值就是100
㈤ C语言 四个过程:预处理,编译,汇编,链接,分别进行了什么过程别度娘。
1.预处理
这个阶段用来处理所有的预处理指令
-
主要是一些宏替换,头文件导入
2.编译
对预处理后的代码进行翻译工作,得到计算机
所认识的格式编译工作得到的结果文件叫做目标文件,
扩展名是.o(编译得到汇编文件(.s)
->经过汇编后得到.o目标文件)
3.链接
把所有的目标文件和其他必要的文件合并在一起
得到最终的可执行文件
㈥ 编译程序预处理干什么
编译预处理是C语言区别于其它高级程序设计语言的特征之一,它属于C语言编译系统的一部分。C程序中使用的编译预处理命令均以#开头,它在C编译系统对源程序进行编译之前,先对程序中这些命令进行“预处理”。编译预处理命令的三种不同形式:宏定义、文件包含和条件编译。
㈦ 预处理命令的条件编译
有些语句希望在条件满足时才编译。
格式:(1)
#ifdef 标识符
程序段1
#else
程序段2
#endif
或
#ifdef
程序段1
#endif
当标识符已经定义时,程序段1才参加编译。
格式:(2)
#ifndef 标识符
#define 标识1
程序段1
#endif
如果标识符没有被定义,则重定义标识1,且执行程序段1。
格式:(3)
#if 表达式1
程序段1
#elif 表达式2
程序段2
……
#elif 表达式n
程序段n
#else
程序段n+1
#endif
当表达式1成立时,编译程序段1,当不成立时,编译程序段2。
使用条件编译可以使目标程序变小,运行时间变短。
预编译使问题或算法的解决方案增多,有助于我们选择合适的解决方案。
此外,还有布局控制:#pragma,这也是我们应用预处理的一个重要方面,主要功能是为编译程序提供非常规的控制流信息。