首页 > 编程笔记 > C语言笔记 阅读:18

C语言条件编译#if、#ifdef和#ifndef的用法(附带实例)

C语言预处理器提供了条件编译功能。一般情况下,源程序中所有的行都参加编译,但是有时我们可能希望只对其中一部分内容在满足一定条件时才进行编译,这时就需要使用一些条件编译命令。

使用条件编译命令可方便地处理程序的调试版本和正式版本,同时还会提高程序的可移植性。

C语言#if命令

#if 命令的一般形式如下:
#if 常数表达式
    语句块
#endif
#if 的基本含义是,如果 #if 命令后的常数表达式为真,则编译 #if 到 #endif 之间的语句块,否则跳过这段代码。

#endif 命令用来表示 #if 语句块的结束。


【实例】利用宏和 #if 语句实现与 50 比较大小的功能。具体代码如下:
#include<stdio.h>                          /*包含头文件*/
#define NUM 50                              /*定义宏,表示NUM替代50*/
void main()                                /*主函数main()*/
{
    int i = 0;                              /*定义变量*/
    #if NUM>50                       /*判断NUM是否大于50*/
        i++;                             //大于50则输出1
    #endif
    #if NUM==50                                /*判断NUM是否等于50*/
        i = i + 50;                             //等于50则输出50
    #endif
    #if NUM<50                                 /*判断NUM是否小于50*/
        i--;                                    //小于50则输出-1
    #endif
        printf("Now i is:%d\n", i);             /*输出结果*/
}
程序运行结果为:

Now i is:50

C语言#elif命令

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

#elif 的一般形式如下:
#if 表达式
    语句块
#elif 表达式1
    语句块
#elif 表达式2
    语句块
...
#elif 表达式n
    语句块
#endif

C语言#ifdef和#ifndef命令

前面介绍的 #if 条件编译命令中,需要判断符号常量所定义的具体值,但有时并不需要判断具体值,只需要知道这个符号常量是否被定义了。这时就不需要使用 #if,而应采用另一种条件编译的方法,即采用 #ifdef 与 #ifndef 命令,它们分别表示“如果有定义”及“如果无定义”。

#ifdef 和 #ifndef 命令需要和宏定义搭配使用。#ifdef 的一般形式如下:
#ifdef 宏替换名
    语句块
#endif
上述代码的含义是,如果宏替换名已被定义过,则对语句块进行编译;如果未定义 #ifdef 后面的宏替换名,则不对语句块进行编译。

#ifdef 可与 #else 连用,一般形式如下:
#ifdef 宏替换名
  语句块1
#else
  语句块2
#endif
上述代码的含义是,如果宏替换名已被定义过,则对语句块1进行编译;如果未定义#ifdef后面的宏替换名,则对语句块2进行编译。

#ifndef 的一般形式如下:
#ifndef 宏替换名
  语句块
#endif
上述代码的含义是,如果未定义 #ifndef 后面的宏替换名,则对语句块进行编译;如果定义了 #ifndef 后面的宏替换名,则不执行语句块。

同样,#ifndef 也可以与 #else 连用,一般形式如下:
#ifndef 宏替换名
  语句块1
#else
  语句块2
#endif
上述代码的含义是,如果未定义 #ifndef 后面的宏替换名,则对语句块 1 进行编译;如果定义了 #ifndef 后面的宏替换名,则对语句块 2 进行编译。

例如:
#include <stdio.h>

// 预定义宏 DEBUG
#define DEBUG

int main() {
    #ifdef DEBUG
        printf("调试信息:变量a的值为5。\n");
    #endif

    int a = 5;
    #ifdef DEBUG
        printf("调试信息:变量b的值为10。\n");
    #endif

    int b = 10;

    #ifndef NDEBUG
        printf("非调试信息:变量c的值为15。\n");
    #else
        printf("非调试信息:变量c的值没有被定义。\n");
    #endif

    // NDEBUG 未被定义,所以下面的代码块将被编译
    int c = 15;

    printf("变量a = %d, 变量b = %d, 变量c = %d\n", a, b, c);
    return 0;
}
在这个例子中:
1) DEBUG 宏被预定义了,所以 #ifdef DEBUG 和 #ifndef NDEBUG 后面的代码块将被编译。这意味着调试信息将被打印出来,并且变量 c 将被定义为 15。

2) 如果你想要编译非调试版本的代码,可以注释掉 #define DEBUG 这一行,或者在编译时定义 -DNDEBUG(这样 NDEBUG 宏就被定义了)。这将导致 #ifdef DEBUG 后面的代码块不被编译,而 #ifndef NDEBUG 后面的代码块将被编译。

3) 当 DEBUG 宏被定义时,#else 后面的代码块(如果有的话)将被忽略。同样,当 NDEBUG 宏未被定义时,#else 后面的代码块将被编译。

通过这种方式,开发者可以根据是否需要调试信息来编译不同的代码块,而不需要修改代码逻辑。这对于在发布版本中移除调试信息非常有用。

相关文章