C/C++ 预处理器详解

来源:互联网 发布:cad网络素材图库 编辑:程序博客网 时间:2024/05/19 11:37

C/C++预处理器的概念及主要意义

C/C++语言通过预处理器提供一些语言功能。从概念上讲,预处理器的编译过程中单独执行的第一个步骤。

预编译器主要包含3个部分

1.文件包含——————程序中包含多个模块,可以使用一个模块中定义的变量和函数,减少重复劳动

2.宏定义——————增强程序的可读性和易更改性

3.条件编译——————减少被编译的语句,减少运行时间。避免重复编译和避免变量重复定义。

同时#pragma还能提供设定编译器的状态或者是指示编译器完成一些特定的动作的功能。

尽管现在预处理器的使用越来越受到一些批评,然而,我们还可以看到绝大部分的代码仍然在使用预处理器,所以,了解并且能使用预处理器是很有必要的。

文件包含 #include

使用格式如下
#include<文件名>
#include"文件名"
文件包含实际上是文件内容的替换
比如有两个文件,一个main.h,另一个main.cpp
//main.hint x;int y;
//main.cpp#include"main.h"int main(){     return x+y;}

预处理器预处理之后交给下一步,进行进一步的编译的实际将会是这样一个文件
//main.cpp//main.hint x;int y;int main(){    return x+y;}


#include的两种格式在功能上会有一些差别。
用引号括起来,则预处理器会首先在源文件所在位置开始查找包含的文件。如果未找到,则到预处理器事先规定的一些位置查找包含的文件。
而,如果用<>括起来,预处理器就会到预处理器事先规定的路径查找包含的文件。

格外注意:不建议在包含文件时使用绝对路径,这将使得程序的移植和兼容性格外差。


宏定义#define

宏的作用便是文本替换,而且这种文本替换的自由度非常大,而且也非常灵活。
如下例
#include<stdio.h>#include<stdlib.h>#define ini int a=5,b=6;printf("%d",a+b);int main(){      ini      system("pause");      return 0;}


这样的代码运行之后,会和
#include<stdio.h>#include<stdlib.h>int main(){      int a=5,b=6;printf("%d",a+b);      system("pause");      return 0;}

有一样的效果
也就是说,预处理器将会将代码中的ini替换成int a=5,b=6;printf("%d",a+b);
除了简单的文本替换之外,也可以定义一些带参数的宏。比如
#define max(A, B) ((A) > (B) ? (A) : (B))
这样就相当于定义了一个求较大值的一个函数了。这里需要再次提醒,带参数的宏依然还是文本替换,预处理器不过是将max(A,B)替换成((A) > (B) ? (A) : (B)),除此之外,不会做任何其他的编译。
使用宏时一定要注意宏文本替换的本质,如果不注意将会造成预想不到的问题,比如
比如说代码
#define a 5+3int main(){    return 4*a;}

也许,一些初学者会认为代码返回的结果是4*8=32。然而,实际上程序返回的结果是23。这是因为,实际交给编译器的代码是如下代码。
int main(){      return 4*5+3;}

所以,笔者在这里推荐使用宏的同时注意使用()运算符,()运算符是C/C++里优先级最高的运算符。宏定义更大的意义在于增强程序的可读性和易更改性。同时在编写跨平台兼容的程序时,宏定义也可以发挥很大的作用。

条件编译

一般的使用格式如下
#ifndef ME#define ME liuzongrun#endif
这样,可以确保#define ME liuzongrun语句只被执行一次,如果很多文件都包含了同一个文件,使用条件编译可以减少编译的语句和减少运行的时间,同时避免重复编译和避免变量重复定义。

#pragma指令是预处理指令中最复杂的指令。过一段时间再来仔细研究,并且讲解记录下来。
原创粉丝点击