预编译的不同形式和辨析整理

来源:互联网 发布:python能做什么游戏 编辑:程序博客网 时间:2024/05/22 05:19

  预编译又称为预处理,在代码编写的过程中是位于编译之前的。简单来说可以认为是做一些代码文本的替换工作,我们最常见的一种就是宏定义和#include类型,预编译过程中处理的是#开头的指令,最常见的预编译指令有:

一、#include指令

  如果是用<>括起来的文件那么就在系统的include目录中寻找文件,如果用""括起来就表示在当前目录中寻找文件(多是程序员自己编写),一般来说,多以h或cpp为后缀,另外需要注意的是如果我们在本应该是include目录中寻找的文件中(也就是本应该用<>的地方)用了“”,它也会先在当前目录下搜索文件,再在系统默认目录下搜索文件。

二、#define指令

  也就是宏定义,最常见的定义常数

  #define a 1

这是最简单的形式,实际上我们用#define还会用于制造一些“函数”,之所以打引号,也就是说其实宏定义所要表达的虽然是函数的意义,但却不是C++里真正的函数,原因是显而易见的。

函数和宏定义的区别

1) 首先在函数中我们的变量是必须要注明其参数类型的,而在宏定义中其实是简单的文本替换,专业的说法可以是宏定义经过预处理器的处理,只负责做形式上的转换,但是不负责做参数类型检查,这也代表着我们在传递参数的时候要做比较细致的检查。

2) 其次宏定义用文本替换的手法一定程度上抹杀了他的智能性,这导致我们在书写宏定义的时候最好在参数两边加上括号,某种程度上,这也是必须要加的。举个非常简单的例子,比如我们要用宏定义来表达一个乘法“函数”

#define mul(A,B) A*Bint main(){printf("%d",(1+2,3));return 0;}

按照常理结果应该是9,但是事实上因为乘法的优先级比加法要高,导致的结果就是1+6=7,所以我们有必要在“参数”的两端加上括号

<pre name="code" class="cpp">#define mul(A,B) (A)*(B) int main(){       printf("%d",(1+2,3));      return 0;}    

但即使是加上了括号,依旧不能避免一些错误的发生,比如有a++形式的,可能因为调用的过程中,盲目的调用a++形式,使得本来程序员只想加一次1,却加了多次1。

3) 在一些情况中,使用宏定义会导致极低的代码执行效率,举例如下

int a[]={9,3,5,2,1,0,8,7,6,4};int max(n){    return n==0?a[0]:MAX(a[n],max(n-1));}int main(){    max(9);    return 0;}

 我们观察上面的MAX函数(注意是大写)如果用宏定义的写法,那么宏展开为( a[n]>max(n-1)?a[n]:max(n-1) ),其中max函数被调用了两遍使得代码执行效率大大降低,而如果我们直接用函数的写法,那么很简单,代码的执行效率是O(n)。

宏定义的一些用法

1) 宏定义的最基本的用法是用来定义常数(略),但是需要注意的一点是,对于同一变量,如果我们重复进行宏定义,那么最终的结果是最后一次的宏定义的结果;

2) 定义标识,常常与#if #ifdef一起联用,不管是#if还是#ifdef最后都是以#endif来标识结尾的。下面进行区分#if和#ifdef。

  首先#ifdef(a)的意思表示是对于a是否被宏定义过进行一轮判断,而#if(a>0)则是表示如果a>0,则执行后面的宏定义内容。相同的是,不管是#if还是#endif,最后都是用#endif来标识一段的结尾,举个ifdef的例子,如果我们事先进行数据选择,不同的是一个是windows下的实例,一个是linux下的实例,那么我们就在不同端的代码中定义一个宏变量windows,当意识到windows已经被宏定义过后,则加入后续代码。

  我们可以简单认为#ifdef后面接的是一个是否被宏定义的变量,而#if后面则是表达式

#if (MAX==10)||(MAX==20) code...#endif
#ifdef (x)    ...code...#endif
3)用于定义一些“函数”



               






0 0
原创粉丝点击