【C语言】#ifdef和#endif条件编译

这篇具有很好参考价值的文章主要介绍了【C语言】#ifdef和#endif条件编译。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

条件编译

一般情况下,源程序中的所有行都参与编译。但有时希望对其中一部分内容只在满足一定条件下才进行编译,即对一部分内容指定编译条件,这就是“条件编译”。有时,希望当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。

条件编译命令指定预处理器依据特定的条件来判断保留或删除某段源代码。
例如,可以使用条件编译让源代码适用于不同的目标系统,而不需要管理该源代码的各种不同版本。

条件编译的格式

条件编译区域以#if#ifdef#ifndef等命令作为开头,以#endif命令结尾。条件编译区域可以有任意数量的#elif命令,但最多一个#else命令。
以#if开头的条件编译区域具有以下格式:

#if 表达式1
[程序段1]
[#elif 表达式2
程序段2]
......
[#elif 表达式n
程序段n]
[#else
程序段n+1]
#endif
  • 语义和正常代码相同,如果表达式1成立,则编译程序段1,如果表达式2成立,则编译程序段2,否则编译程序段n+1
  • 预编译指令中的表达式与C语言本身的表达式基本一致,如逻辑运算、算术运算、位运算等均可以在预编译指令中使用
  • C语言的代码时先编译再执行,预编译指令时在编译之前进行处理,通过预编译进行宏替换、条件选择代码段,生成最后的待编译代码,最后进行编译
  • 不能忘记#endif

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

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

常见形式

#ifdef 标识符
程序段1
#else
程序段2
#endif

作用:当标识符已经被定义过(一般是用#define命令定义),则对程序段1进行编译,否则编译程序段2
其中#else部分也可以没有,即:

#ifdef
程序段1
#endif

在头文件中使用#ifdef和#ifndef是非常重要的,可以防止双重定义的错误。例如:在头文件aaa.h中定义了类aaa

class aaa{
};

如果两次#include "aaa.h"就会出错(不一定是直接两次,有可能两个不同的头文件中都包含了这个头文件),因为相同的类不能定义两次,所以需要修改aaa.h
有时,在b.h中#inclde "a.h",在c.h中#inclde "b.h"#inclde "c.h",这时,如果不用ifndef/endif,就会包含两次a.h产生错误

#ifndef _aaa_
#define _aaa_
class aaa{
};
#endif

可以避免问题。因为如果已经包含某头文件,_aaa_就已经有定义,那么#ifndef条件为假,就不会执行#ifndef和#endif之间的程序段,不会再次执行对类aaa的定义了。

defined运算符

一元运算符defined可以出现在#if或#elif命令的条件中。形式如下:

defined 标识符
defined (标识符)

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

defined运算符相对于#ifdef和#ifndef命令的优点是:可以在更大型的预处理器表达式中使用它的值。例如:

#if defined( _unix_ )&& defined( _GNUC_ )
#endif

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

#if的使用

#if 表达式
程序段
#endif

if后面接表达式,如果表达式成立,就会把后面的程序段编译进去(注意是编译不是执行)

#if defined的使用

#if defined ()
程序段
#endif

#if后面接一个宏,如果前面定义过这个宏,编译器就会编译程序段,如果没有定义过,就不会编译。不管该宏定义的是什么以及对不对。

#if和#elif命令

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

  1. 不能再#if或#elif表达式中使用类型转换运算符
  2. 可以使用预处理运算符defined
  3. 再预处理器展开所有宏,并计算完所有的defined表达式后,会使用字符o替换掉表达式中所有其他标识符或关键字
  4. 表达式中所有带符号值都具有intmax_t类型,并且所有无符号值都具有uintmax_t类型。字符常量也会受该规则的影响。intmax_t和unitmax_t定义在头文件stdint.h中。
  5. 预处理器会把字符常量和字符串变量中的字符与转义序列转换成字符集中对应的字符。然而,字符常量再预处理器表达式和在后期编译阶段是否具有相同的值,取决于实现版本。

#ifdef和#ifndef命令

通过#ifdef和#ifndef命令测试某个宏是否已被定义。

#ifdef 标识符
#ifndef 标识符

等同于:

#if defined (标识符)
#if !defined (标识符)

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

#if #endif的用法

#ifdef #endif的用法

#ifdef和#endif必须成对使用。理论上可以出现在任何地方(头文件和实现文件中),通常为了放置头文件被多次包含,在头文件中使用是必须的:

#ifndef MY_HEAD_H	//头文件开头,注意不要和其它头文件冲突
头文件声明
#endif

总结

把头文件的内容都放在#ifndef和#endif中。无论头文件会不会被多个文件引用,都加上条件编译。一般格式为:

#ifndef <标识>
#define <标识>
程序段
#endif

标识理论上可以自由命名,但是每个头文件的这个标识都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的.也写成下划线。如:stdio.h文章来源地址https://www.toymoban.com/news/detail-430363.html

#ifndef _STDIO_H_
#define _STDIO_H_
程序段
#endif

到了这里,关于【C语言】#ifdef和#endif条件编译的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【正点原子STM32】C语言重点知识(配置MDK支持C99、位操作清零置一、带参数的宏定义、头文件的条件编译和代码条件编译、关键字、结构体指针、代码规范)

    一、stdint.h简介 配置MDK支持C99 二、位操作 如何给寄存器某个位赋值(清零置一) 三、宏定义 带参数的宏定义 四、条件编译 头文件的条件编译和代码条件编译 五、extern声明 六、类型别名(typedef) 类型别名应用 七、结构体 应用举例(定义使用) 应用举例(ST源码,使用类型

    2024年02月19日
    浏览(29)
  • C语言-程序环境和预处理(2)--带副作用的宏参数,宏与函数的对比,#undef,条件编译,文件包含

    上一篇文章–《C语言-程序环境和预处理(1)》讲述了程序的翻译环境和执行环境,编译、连接,预定义符号,#define,#符号和##符号的相关知识。 链接: 《C语言-程序环境和预处理(1)》 本篇文章,讲述带副作用的宏参数,宏与函数的对比,#undef,条件编译,文件包含的相

    2024年02月08日
    浏览(49)
  • 【05】STM32·HAL库开发-C语言基础知识 | stdint.h介绍 | 位操作 | 宏定义的使用 | 条件编译 | extern声明 | typdef使用 | 结构体、指针、代码规范介绍。

      stdint.h 是从 C99 中引进的一个标准 C 库的文件,可以在MDK5的安装路径:D:MDK5.34ARMARMCCinclude中找到。   stdint.h 定义了很多类型别名,将有符号的char类型定义别名为int8_t等,使用此套别名有易于移植。   在MDK中需要配置才能支持使用S99标准, 默认是勾选的 。   只

    2024年02月08日
    浏览(33)
  • #if、 #ifdef、#else、#endif等宏详解

    这些都是 条件编译 命令 #ifdef 语句,对应 #endif 语句,可以区隔一些与特定 头文件 、 程序库 和其他 文件版本 有关的代码。可翻译为:如果宏定义了语句1则执行程序2。 #ifdef 等宏是为了进行条件编译。一般情况下, 源程序中所有的行都参加编译 。但是有时希望对其中一部

    2023年04月13日
    浏览(29)
  • stm32中代码#ifdef __cplusplus extern “C“ {#endif的用途

      在大部分开源项目的stm32中,我们常常会看到这段代码: #ifdef __cplusplus extern \\\"C\\\" { #endif 这是一段 C/C++ 代码中常见的条件编译指令,用于处理 C++ 中的外部链接性问题。 #ifdef __cplusplus : 这是一个条件预处理指令,用于检查是否定义了宏 __cplusplus 。在 C++ 编译环境中,这个宏会

    2024年04月16日
    浏览(22)
  • 【C语言】--编译及编译器

    夫学须静也,才须学也;非学无以广才,非志无以成学 个人主页:【😊个人主页】 系列专栏:【❤️系列专栏】 C语言一直以来都是初入编程的小白们的必修课,作为程序员必学语言之一,C语言自然有属于它的奥秘,接下来就由我来带领大家走进C语言的世界吧🚗🚗🚗 1、

    2024年02月13日
    浏览(44)
  • 编译原理课程设计--C语言编译器

    源程序1: 源程序1词法分析结果: 与程序1语法分析结果(部分) 源程序1四元式: 源程序1优化后的四元式: action-goto表(部分) 文件目录: (1)掌握语义分析过程,即语法制导翻译过程。 (2)在语法分析的LR分析程序中的基础上添加程序,进行语义分析,生成源程序的四

    2024年02月08日
    浏览(43)
  • 安卓系统--翻译手机rom语言 添加多国语言 编译apk 反编译ODEX 工具步骤解析

    很多小品牌机型不具备多语言设置。国内大都是中文。要想换为其他语言除非固件支持。例如国际版固件等等。大厂基本都有中文或者英文或者其他语言配置。而小品牌机型只能通过修改rom来达到多语言调用. 今天给友友介绍一款工具,可以用来翻译手机rom语言。添加多国语

    2024年02月04日
    浏览(34)
  • Python 既是解释型语言,也是编译型语言

    哈喽大家好,我是咸鱼 不知道有没有小伙伴跟我一样,刚开始学习 Python 的时候都听说过 Python 是一种解释型语言,因为它在运行的时候会逐行解释并执行,而 C++ 这种是编译型语言 不过我今天看到了一篇文章,作者提出 Python 其实也有编译的过程,解释器会先编译再执行 不

    2024年02月05日
    浏览(37)
  • (嵌入式c语言)c语言编译常见错误

    预处理(gcc -E -o)-编译(gcc -S -o)-汇编(gcc -c -o)-链接(gcc -o) 将代码中的define 和 include替换成实体码  define和include不是,是在编译过程中处理的。 包含 #include 包含头文件 宏 #define 宏  替换  不会进行语法检查 #define 宏  宏体   宏体要加括号 #define ABC 

    2024年02月11日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包