您的位置:首页 > 编程语言 > C语言/C++

C++编译预处理:宏定义指令、文件包含指令和条件编译指令

2017-08-04 14:20 615 查看


不带参数的宏定义:用来产生与一个字符串(即宏名)对应的常量字符串,格式为:

   #define 宏名 常量串

带参数的宏定义:带参宏定义的形式很象定义一个函数,格式为:

   #define 宏名(形参表) 表达式串

处理过程:编译预处理后产生一个中间文件,文件中所有宏名(如果是带参数的宏,则宏名包括参数表在内)均用其对应的常量串或表达式串代替。替换过程称为“宏替换”或“宏展开”。

举例:

使用指令:#define PI 3.1415926

则程序中可以使用标识符PI,编译预处理后产生一个中间文件,文件中所有PI被替换3.1415926。
使用指令:#define S(a,b) (a)*(b)/2

则程序中可使用S(a,b),编译预处理后产生中间文件,其中S(a,b)被替换成(a)*(b)/2。

几点注意:
宏替换只是字符串和标识符之间的简单替换,预处理本身不做任何数据类型和合法性检查,也不分配内存单元。
宏定义时,形参通常要用括号括起来,否则容易导致逻辑错误。例如,如果定义:

   #define S(a,b) a*b/2

那么程序中的S(3+5,4+2)就会被宏展开为3+5*4+2/2,不符合定义的真正的意图。
带参宏定义形式上象定义函数,但它与函数的本质不同。宏定义只是产生字符串替代,不存在分配内存和参数传递。

文件包含指令

文件包含用#include指令,预处理后将指令中指明的源程序文件嵌入到当前源程序文件的指令位置处。有2种格式:
第一种方式,格式为:

  #include<
文件名>
预处理器将在include子目录下搜索由文件名所指明的文件。这种方式称为“标准方式”,适用于嵌入C++提供的头文件,因为这些头文件一般都存在C++系统目录的include子目录下。
第二种方式,格式为:

  #include ″文件名″
预处理器将首先在当前文件所在目录下搜索,如果找不到再按标准方式搜索。这种方式适用于嵌入用户自己建立的头文件。

一个被包含的头文件中还可以有#include指令,即include指令可以嵌套。但是,如果同一个头文件在同一个源程序文件中被重复包含,就会出现标识符重复定义的错误。

例如:头文件f2.h中包含了f1.h,如果文件f3.cpp中既包含f1.h,又包含f2.h,那么编译将提示错误,原因是f1.h被包含了两次,那么其中定义的标识符在f3.cpp中就被重复定义。

避免重复包含可以用“条件编译”指令。

条件编译指令

当希望在不同条件下编译程序的不同部分,这种情况就要使用“条件编译”指令。

条件编译指令包括:#if、#else、#ifdef、#ifndef、#endif、#undef等。可分为两类:
用宏名作为编译的条件,格式为:

   #ifdef<宏名>

  < 程序段1>

   [#else

  < 程序段2>]

   #endif
用表达式的值作为编译条件,格式为:

   #if< 表达式>

  < 程序段1>

   [#else

  < 程序段2>]

   #endif

其中,“程序段”可以是程序也可以是编译预处理指令。

实际中,在调试程序时常常要输出调试信息,而调试完后不需要输出这些信息,则可以把输出调试信息的语句用条件编译指令括起来,通过在该指令前面安排宏定义来控制编译不同的程序段。形式如下:

  #ifdef DEBUG

   cout<<″a=″<<a<<′\t′<<″x=″<<x<<endl;

   #endif

在程序调试期间,在该条件编译指令前增加宏定义:

  #define DEBUG

调试好后,删除DEBUG宏定义,将源程序重新编译一次。

几点说明:
#ifndef与#ifdef作用一样,只是选择的条件相反。
#undef指令用来取消#define指令所定义的符号,这样可以根据需要打开和关闭符号。 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: