c++中 #if #ifdef #ifndef #elif #else #endif的用法

#if, #ifdef, #ifndef, #else, #elif, #endif
这些命令让编译器进行简单的逻辑控制. 当一个文件被编译时, 你可以使用这些命令使某些行保留或者是去处.

#if expression

如果表达式(expression)的值是"真"(true),那么紧随该命令的代码将会被编译.

#ifdef macro

如果"macro"已经在一个#define声明中定义了, 那么紧随该命令的代码将会被编译.

#ifndef macro

如果"macro"未在一个#define声明中定义, 那么紧随命令的代码将会被编译.

一些小边注: 命令#elif是"elseif"的一种缩写,并且他可以想你所意愿的一样工作. 你也可以在一个#if后插入一个"defined"或者"!defined"以获得更多的功能.

这里是一部分例子:

#ifdef DEBUG
  cout << "This is the test version, i=" << i << endl;
#else
  cout << "This is the production version!" << endl;
#endif

你应该注意到第二个例子比在你的代码中插入多个"cout"进行调试的方法更简单.

 

在实现不同模块的代码时,并且不同模块存在复用的代码时,可以采用预处理宏定义#ifdef来实现不同的分支处理。

1、参考

https://bbs.csdn.net/topics/210046082

2、预处理及其作用

预处理指令共有三种:

  • 宏定义 #define M 2
  • 条件编译 #ifdef/#if/#elif/#else/#endif
  • 文件包含 #include

预处理就是在进行编译的第一遍词法扫描和语法分析之前所作的工作。说白了,就是对源文件进行编译前,先对预处理部分进行处理,然后对处理后的代码进行编译。这样做的好处是,经过处理后的代码,将会变的很精短。

这里主要讲解预处理中条件编译#ifdef/#if/#elif/#else/#endif使用的几种方式。

3、预处理的条件编译#ifdef/#if/#elif/#else/#endif使用的几种方式

方式一:

#ifdef _XXXX
...程序段1...
#else
...程序段2...
#endif

这表明如果标识符_XXXX已被#define命令定义过则对程序段1进行编译;否则对程序段2进行编译。
注意:这种方式#ifdef后面只能跟一个宏变量。

方式二:

#ifndef _XXXX
...程序段1...
#else
...程序段2...
#endif

与方式一相反。

方式三:

#if 常量 
...程序段1...
#else
...程序段2...
#endif 

这种方法可以将测试代码加进来。当需要开启测试的时候,只要将常量变1就好了。而不要测试的时候,只要将常量变0。

方式四:

#if defined(Macro1) || defined(Macro2) || defined(Macro3)
...程序段1...
#elif defined(Macro4)
...程序段2...
#endif

方式四这种方法比较灵活,可以使用多个宏变量的组合(或||or与&&),推荐使用这种方法!

方式五:

#if !defined(Macro1) || defined(Macro2) || defined(Macro3)
...程序段1...
#elif !defined(Macro4)
...程序段2...
#endif

预处理器会依次计算条件表达式,直到发现结果非 0(也就是 true)的条件表达式。预处理器会保留对应组内的源代码,以供后续处理。如果找不到值为 true 的表达式,并且该条件式编译区域中包含 #else 命令,则保留 #else 命令组内的代码。

组 1、组 2 等代码段,可以包含任意 C 源代码,也可以包含更多的命令,包括嵌套的条件式编译命令。在预处理阶段结束时,没有被预处理器保留以用于后续处理的组会从程序中全部删除。

#if 和 #elif 命令

作为 #if 或 #elif 命令条件的表达式,必须是整数常量预处理器表达式。这与普通的整数常量表达式不同,主要区别在于:

(1) 不能在 #if 或 #elif 表达式中使用类型转换运算符。

(2) 可以使用预处理运算符 defined。

(3) 在预处理器展开所有宏,并且计算完所有 defined 表达式之后,会使用字符 o 替换掉表达式中所有其他标识符或关键字。

(4) 表达式中所有带符号值都具有 intmax_t 类型,并且所有无符号值都具有 uintmax_t 类型。字符常量也会受该规则的影响。intmax_t 和 uintmax_t 定义在头文件 stdint.h 中。

(5) 预处理器会把字符常量和字符串字面量中的字符与转义序列转换成运行字符集中对应的字符。然而,字符常量在预处理器表达式和在后期编译阶段是否具有相同的值,取决于实现版本。

defined 运算符

一元运算符 defined 可以出现在 #if 或 #elif 命令的条件中。它的形式如下:
  1. defined 标识符
  2. defined (标识符)

如果指定的  identifier 是一个宏名称(也就是说,它已被 #define 命令定义,并且未被 #undef 命令取消定义),则 defined 表达式会生成值 1。否则,defined 表达式会生成值 0。

defined 运算符相对于 #ifdef 和 #ifndef 命令的优点是:你可以在更大型的预处理器表达式中使用它的值。如下例所示:
  1. #if defined( __unix__ ) && defined( __GNUC__ )
  2. /* ... */
  3. #endif

大多数编译器会提供预定义宏,例如上例所使用的宏,它用来识别目标系统和编译器。因此,在 Unix 系统中,通常预先定义好了宏 __unix__,而 GCC 编译器则会预先定义好了宏 __GNUC__。类似地,微软 Windows 平台上的 Visual C 编译器会自动定义好宏 _WIN32 和宏 _MSC_VER。

#ifdef 和 #ifndef 命令

你可以通过 #ifdef 和 #ifndef 命令测试某个宏是否已被定义。它们的语法是:
  1. #ifdef 标识符
  2. #ifndef 标识符

这等同于下面的 #if 命令:
  1. #if defined 标识符
  2. #if !defined 标识符

如果 identifier 不是宏名称,则 #ifndef 标识符后面的条件代码被保留。

这些命令可以让编译器进行简单的逻辑控制,当一个文件被编译时,你可以用这些命令去决定某些代码的去留,

  这些命令式条件编译的命令。

常见的条件编译的三种形式:

  ①第一种形式: 
    #if defined(或者是ifdef)<标识符(条件)> 

    <程序段1>

     [#else 
    <程序段2>] 

    #endif 
②第二种形式: 
    #if !defined(或者是ifndef)<标识符(条件)> 

    <程序段1> 

    [#else 
    <程序段2>] 

    #endif 
③第三种形式:

   #ifdef … 

  [#elif … ] 

  [#elif …] 

  #else …  

  #endif

示例:

#include <iostream>

using namespace std;

int main()
{
#if DEBUG  /*或者是#ifdef DEBUG*/
cout << "条件成立,DEBUG已经定义了!" <<endl;
#else
cout << "条件不成立,DEBUG还没定义" <<endl;
#endif
return 0;
}

//结果输出:条件不成立,DEBUG还没定义

//如果是添加了#define DEBUG ,输出结果是:条件成立,DEBUG已经定义了!

#include <iostream>
using namespace std;
#define DEBUG
int main()
{
#ifdef DEBUG /*或者是#ifdef DEBUG*/
cout << "条件成立,DEBUG已经定义了!" <<endl;
#else
cout << "条件不成立,DEBUG还没定义" <<endl;
#endif
return 0;
}

//要注意的是,如果是#define 宏名,没有宏体如 #define DEBUG,就必须使用#ifdef或#ifndef与之对应,

//如果是#define 宏名 宏体,如 #define NUM 1,#if 和#ifdef都可以使用。

/*

#define的用法:

 

*/

示例二:

#include <iostream>
using namespace std;

#define NUM  10

int main()
{
        #ifndef NUM
        cout << "NUM没有定义!"<<endl;
        #elif NUM >= 100
        cout << "NUM >100" <<endl;
        #elif NUM <100 && NUM >10
        cout << "10 < NUM < 100" <<endl;
        #elif NUM == 10
        cout << "NUM ==10" <<endl;
        #else
        cout << "NUM < 10" << endl;
        #endif
        return 0;
}
//输出NUM ==10

#ifdef的用法

灵活使用#ifdef指示符,我们可以区隔一些与特定头文件、程序库和其他文件版本有关的代码。
代码举例:新建define.cpp文件

  1.  
    #include "iostream.h"
  2.  
    int main()
  3.  
    {
  4.  
    #ifdef DEBUG
  5.  
    cout<< "Beginning execution of main()";
  6.  
    #endif
  7.  
    return 0;
  8.  
    }

 运行结果:Press any key to continue

改写代码如下: 

  1.  
    #include "iostream.h"
  2.  
    #define DEBUG
  3.  
    int main()
  4.  
    {
  5.  
    #ifdef DEBUG
  6.  
    cout<< "Beginning execution of main()";
  7.  
    #endif
  8.  
    return 0;
  9.  
    }

运行结果为:Beginning execution of main()
Press any key to continue

 更一般的情况是,#define语句是包含在一个特定的头文件中。
比如,新建头文件head.h,在文件中加入代码:

  1.  
    #ifndef DEBUG
  2.  
    #define DEBUG
  3.  
    #endif
  4.  
     
  5.  
    //而在define.cpp源文件中,代码修改如下:
  6.  
    #include "iostream.h"
  7.  
    #include "head.h"
  8.  
    int main(){
  9.  
    #ifdef DEBUG
  10.  
    cout<< "Beginning execution of main()";
  11.  
    #endif
  12.  
    return 0;
  13.  
posted @ 2020-10-20 09:33  konglingbin  阅读(6025)  评论(0编辑  收藏  举报