当前位置 : 主页 > 编程语言 > 其它开发 >

条件编译

来源:互联网 收集:自由互联 发布时间:2022-07-01
在看开源库时,遇到很多条件编译指令,系统学习一波,内容转载自:https://www.cnblogs.com/wind-under-the-wing/p/14018825.html,并加入自己的笔记。 作用 根据不同情况编译不同代码、产生不同目

在看开源库时,遇到很多条件编译指令,系统学习一波,内容转载自:https://www.cnblogs.com/wind-under-the-wing/p/14018825.html,并加入自己的笔记。

作用

根据不同情况编译不同代码、产生不同目标文件的机制,称为条件编译,条件编译是预处理程序的功能,不是编译器的功能。

条件编译可以让程序更加容易移植,只需改变文件开头部分的关键定义,就可以根据不同的系统设置不同的值和包含不同的文件。

使用 (#if)

1、用法

#if 整型常量表达式1
    程序段1
#elif 整型常量表达式2
    程序段2
#elif 整型常量表达式3
    程序段3
#else
    程序段4
#endif

2、说明
若“整型常量表达式1”计算后的值为真(非0),则对”程序段1“进行编译,否则计算“整型常量表达式2”,若为真,则对”程序段2“进行编译,否则就继续往下匹配,直到表达式计算的值为真,或者到”#else“。
注意:“#if” 要求判断条件为“整型常量表达式”,也就是说,表达式中不能包含变量,而且结果必须是整数

3、应用
现在要开发一个C语言程序,让它输出红色的文字,并且要求跨平台,在 Windows 和 Linux 下都能运行,怎么办呢?这个程序的难点在于,不同平台下控制文字颜色的代码不一样,我们必须要能够识别出不同的平台。Windows 有专有的宏_WIN32,Linux 有专有的宏__linux__,此时可以使用预处理命令进行条件编译。

#include <stdio.h>
int main(){
    #if _WIN32
        system("color 0c");
        printf("http://c.biancheng.net\n");
    #elif __linux__
        printf("\033[22;31mhttp://c.biancheng.net\n\033[22;30m");
    #else
        printf("http://c.biancheng.net\n");
    #endif
    return 0;
}
(#ifdef)

1、用法

#ifdef  宏名
    程序段1
#else
    程序段2
#endif

2、说明
如果当前的“宏(宏名)”已被定义过,则对“程序段1”进行编译,否则对“程序段2”进行编译,也可以省略 #else:

#ifdef  宏名
    程序段
#endif

3、应用
VS/VC 有两种编译模式,Debug 和 Release。在学习过程中,我们通常使用 Debug 模式,这样便于程序的调试;而最终发布的程序,要使用 Release 模式,这样编译器会进行很多优化,提高程序运行效率,删除冗余信息。

#include <stdio.h>
#include <stdlib.h>
int main(){
    #ifdef _DEBUG
        printf("正在使用 Debug 模式编译程序...\n");
    #else
        printf("正在使用 Release 模式编译程序...\n");
    #endif
    system("pause");
    return 0;
}

另外,较新的编译器提供另一种方法测试名称是否已经定义,用(#if defined (_DEBUG))代替(#ifdef _DEBUG

(#ifndef)

1、用法

#ifndef 宏名
    程序段1
#else
    程序段2
#endif

2、说明
与(#ifdef) 相比,仅仅是将 (#ifdef) 改为了 (#ifndef),意思是,如果当前的宏未被定义,则对“程序段1”进行编译,否则对“程序段2”进行编译,这与(#ifdef) 的功能正好相反。

3、应用
(#ifnfed)常用于防止多次包含一个文件。

那为什么会多次包含一个文件?

许多被包含的文件中都包含着其他文件,所以显式包含的文件中可能包含着已经包含的其他文件。

这会存在什么问题?

在被包含的文件中有某些项(如结构类的声明)只能在一个文件中出现一次。
举例:
image

扩展指令 (#undef)

用于取消已经定义的(#define)指令,即:

#define LIMIT 400
....
#undef LIMIT

移除了LIMIT定义,可以把LIMIT重新定义为新值。即使没有定义过LIMIT,使用(#undef LIMIT)依然有效,所以若想使用一个名称,但不确定是否用过,为了安全,最好先使用(#undef)!

预定义宏

image
image

(#line)

(#line)可以重置“LINE”和“FILE”宏,即行号和文件名。
举例:

#line 1000  //把当前行号重置为1000
#line 10 "colle.c" //把行号重置为10,文件名重置为colle.c
(#error)

(#error)可以让预处理器发出一条错误信息,该消息包含指令中的文本。
举例:

#if __STDC_VERSION__ !=201112L
#error Not C11

#endif

image

参考

1、https://wenku.baidu.com/view/9f4bd14e551252d380eb6294dd88d0d233d43c97.html
2、http://t.zoukankan.com/MuyouSome-p-3376727.html

上一篇:Windows 启动过程
下一篇:没有了
网友评论