#if #ifdef #ifndef #undef 条件编译

1、#if命令

  #if的基本含义:如果#if命令后的参数表达式为真,则编译#if到#endif之间的程序段,#endif

命令用来表示#if段的结束,否则跳过这段程序。

  #if命令的一般格式如下:

  

#if 常数表达式
    语句段
#endif

如果“常数表达式”为真,则该段程序被编译。

例子:

#include <stdio.h>

#define NUM 50

int main(void) { 
      
    int i = 0;
    #if NUM > 50
     i ++;
    #endif
    
    #if NUM == 50
     i = i + 50;
    #endif
    
    #if NUM < 50
     i --;
    #endif
      
    printf("Now i is :%d\n", i); 
    

	return 0;
}

运行结果:

Now i is :50

如果将语句

#define NUM 50

改为:

#define NUM 10

则程序运行结果如下:

Now i is :-1

同样,如果将语句

#define NUM 50

改为:

#define NUM 100

则程序运行结果为:

Now i is :1

#else 的作用是为#if为假时提供另一种选择,#else的使用例子:

#include <stdio.h>

#define NUM 50

int main(void) { 
      
    int i = 0;
    #if NUM > 50
     i ++;
    
    #else
    #if NUM == 50
     i = i + 50;
    
    #else
     i --;
     
    #endif
    #endif
      
    printf("Now i is :%d\n", i); 
    

	return 0;
}

程序运行结果为:

Now i is :50

   #elif 命令用来建立一种“如果......或者如果......”阶梯状多重编译操作选择,这与多分支if语句中的

else if 类似。

  #elif命令的一般格式如下:

 

#if 表达式
语句段
#elif 表达式1
语句段
#elif 表达式2
语句段
...
#elif 表达式n
语句段
#endif

上面的示例可以修改为:

#include <stdio.h>

#define NUM 50

int main(void) { 
      
    int i = 0;
    #if NUM > 50
     i ++;
    
    #elif NUM == 50
     i = i + 50;
    
    #else
     i --;
     
    #endif
      
    printf("Now i is :%d\n", i); 
    

	return 0;
}

运行结果不变:

Now i is :50

2、#ifdef 和 #ifndef命令

  前面介绍的#if条件编译命令中,需要判断符号常量所定义的具体值,但有时并不需要判断具体值。

只要知道这个符号常量是否被定义了,这时就不需要使用#if,而采用另一种条件编译的办法,即#ifdef

与#ifndef命令,它们分别表示“如果有定义”及“如果无定义”。

  #ifdef的一般格式如下:

#ifdef 宏替换名
     语句段
#endif

     其含义是:如果“宏替换名”已被定义过,则对“语句段”进行编译,如果没有定义#ifdef后面的“宏替换名”,

则不过“语句段”进行编译。

   #ifdef 可与#else连用,构成的一般格式如下:

 

#ifdef 宏替换名
   语句段1
#else
   语句段2
#endif

  其含义是:如果“宏替换名”已被定义过,则对“语句段1”进行编译;如果没有定义#ifdef后面的“宏替换名”,

则对“语句段2”进行编译。 

 

 

 

#ifndef的一般格式如下:

#ifndef 宏替换名
    
   语句段

#endif

     其含义是:如果未定义#ifndef后面的“宏替换名”,则对“语句段1”进行编译;如果定义了#ifndef后面的“宏替换名”,

则不执行语句段。

  同样,#ifndef也可以与#else连用,构成的一般格式如下:

#ifndef 宏替换名
    
   语句段1

#else

   语句段2
  

#endif

    其含义是:如果未定义#ifndef后面的“宏替换名”,则对“语句段1”进行编译;如果定义了#ifndef后面的“宏替换名”,

则对“语句段2”进行编译。

   

#include <stdio.h>

#define STR  "diligence is the parent of success\n"

int main(void) { 
      
    #ifdef STR
    printf(STR);
    #else
    printf("idleness is the root of all evil\n");
    #endif
    
    printf("\n");
    
    #ifndef ABC
    printf("idleness is the root of all evil\n");
    #else
    printf(STR);
    #endif

	return 0;
}

运行结果为:

diligence is the parent of success

idleness is the root of all evil

3、#undef命令

#undef命令的一般格式如下:

#undef 宏替换名
#include <stdio.h>

#define NUM 50

int main(void) { 
      
    int i = 0;
    #ifdef NUM
     
     i = 50;
     
    #endif
      
    printf("Now i is :%d\n", i); 
    
    #undef NUM
    
     i = 0;
   
    #ifdef NUM 
    
     i  = 50;
    
    #endif
    
    printf("Now i is :%d\n", i); 
    

	return 0;
}

说明:#undef的主要目的是将宏名局限在仅需要它们的代码段中,比如上例#undef之后 NUM定义失效,i的值没有变成50。

4、#line命令

    #line命令用来改变_LINE_ 和 _FILE_的内容(_LINE_中存放的是当前编译行的行号,_FILE_中存放的

是当前编译的文件名),主要用于调试及其他特殊应用。

   #line的一般格式如下:

#line 行号["文件名"]

  其中,“行号”为任一正整数,代表源程序中当前行号;可选的“文件名”为任一有效文件标识符,代表源文件的名称。

 

#line 100 "13.7.C"
#include <stdio.h>


int main(void) { 
      
   printf("1.The current line NO.:%d\n", __LINE__);
   printf("2.The current line NO.:%d\n", __LINE__);
   
   printf("3.The current file name is:%s\n", __FILE__);

	return 0;
}

输出结果为:

1.The current line NO.:105
2.The current line NO.:106
3.The current file name is:13.7.C

可以看到,可以通过#line改变行号和文件名

<think> 我们正在讨论C/C++中的预处理指令,特别是#ifndef、#define、#include、#ifdef和#endif。这些指令在头文件保护和条件编译中扮演重要角色。根据引用内容,我们可以总结如下: 1. #include:用于包含头文件,将指定文件的内容插入到该指令所在的位置。 2. #define:用于定义宏,可以是常量、函数宏或标识符。 3. #ifndef:如果指定的宏没有被定义,则编译其后的代码,直到遇到#endif。 4. #ifdef:如果指定的宏已经定义,则编译其后的代码,直到遇到#endif。 5. #endif:结束条件编译块。 其中,头文件保护(防止重复包含)的典型结构是: ```cpp #ifndef HEADER_NAME_H #define HEADER_NAME_H // 头文件内容 #endif ``` 当同一个头文件被多次包含时,第一次包含会定义宏,后续包含会因为#ifndef条件不成立而跳过内容,避免重复定义。 另外,条件编译允许根据不同的条件编译不同的代码段,常用于跨平台或调试。 现在,根据用户的问题,我将详细解释这些指令的作用和用法,并参考引用内容。 </think> 在 C/C++ 中,预处理指令是编译器在正式编译前处理的命令,主要用于条件编译和文件包含。以下是对关键指令的详细说明: ### 1. `#include` - 文件包含 **作用**:将指定文件的内容插入到当前位置 **用法**: ```cpp #include <iostream> // 包含标准库头文件 #include "myheader.h" // 包含自定义头文件 ``` - 尖括号 `<>` 用于标准库,双引号 `""` 用于用户自定义文件 - 可能引发重复包含问题(需配合 `#ifndef` 解决) ### 2. `#define` - 宏定义 **作用**:定义宏或常量 **用法**: ```cpp #define PI 3.14 // 定义常量 #define MAX(a,b) ((a)>(b)?(a):(b)) // 定义函数宏 ``` - 宏在预处理阶段进行文本替换 - 常量宏通常全大写以示区别 ### 3. `#ifndef` 与 `#endif` - 头文件保护 **作用**:防止头文件被重复包含 **典型结构**: ```cpp // myheader.h #ifndef MYHEADER_H // 如果未定义 MYHEADER_H #define MYHEADER_H // 则定义该宏 // 头文件实际内容 class MyClass { public: void doSomething(); }; #endif // MYHEADER_H // 结束条件编译 ``` **工作原理**[^1]: 1. 首次包含时 `MYHEADER_H` 未定义,执行 `#ifndef` 后的代码 2. 后续包含时因宏已定义,跳过整个代码块 3. `#endif` 标记条件编译块的结束 ### 4. `#ifdef` - 条件编译 **作用**:检查宏是否已定义,用于平台适配或调试 **用法**: ```cpp #ifdef DEBUG std::cout << "Debug mode enabled"; // 仅当 DEBUG 定义时编译 #endif ``` **常见场景**: - 跨平台代码:`#ifdef _WIN32` / `#ifdef __linux__` - 功能开关:`#ifdef USE_FEATURE_X` ### 5. 完整指令清单 | 指令 | 作用 | |------------|-------------------------------| | `#if` | 表达式为真时编译代码 | | `#elif` | 等效于 `#else` + `#if` | | `#undef` | 取消已定义的宏 | | `#error` | 强制编译错误并输出消息 | ### 示例解析 ```cpp #ifndef SALES_DATA_H #define SALES_DATA_H #include <string> struct Sales_data { std::string bookNo; unsigned units_sold = 0; double revenue = 0.00; }; #endif ``` 此结构确保 `Sales_data` 声明仅被包含一次[^4],避免重复定义错误。 > **关键点总结** > - `#ifndef`/`#endif` 是头文件保护的**黄金标准** > - `#define` 在保护结构中用于**标记已包含状态** > - `#ifdef` 多用于**运行时配置**而非头文件保护 > - 所有条件编译指令必须**严格配对**(如 `#ifdef` 必须对应 `#endif`)[^3]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WangLanguager

您的鼓励是对我最大的支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值