learn_C_deep_14 (条件编译的基本使用与理解)

news/2025/2/19 8:33:19/

目录

条件编译

1.条件编译如何使用?

2.为何要有条件编译?

3. 条件编译都在哪些地方用?


条件编译

1.条件编译如何使用?

        C语言的条件编译是一种在程序编译时根据条件选择不同代码段进行编译的技术。条件编译可以用于实现代码跨平台,开启或关闭某些功能,以及调试等情况。

#ifdef` 指令用于判断某个宏是否被定义,不论我们定义的宏为真为假,如果被定义则编译下面的代码块,否则跳过:

#include <stdio.h>
//#define PTINT
//#define PTINT 1  //真
//#define PTINT 0  //假
int main()
{
#ifdef PRINT //PRINT并没有被[定义],所以代码只保留#else部分printf("hello world!\n");
#elseprintf("Non Message!\n");//这句代码会被输出
#endifreturn 0;
}

与 `#ifdef` 相对应的是 `#ifndef`,它用于判断某个宏是否未被定义

#include <stdio.h>
//#define DEBUG
int main()
{
#ifndef DEBUG //DEBUG并没有被[定义],所以代码会输出#ifndef内容printf("hello debug\n");//这句代码会被输出
#elseprintf("hello release\n");
#endifreturn 0;
}

`#if` 指令可以根据表达式的值来判断是否编译下面的代码块。

// 单个条件的情况
#include <stdio.h>
//报错
//#define DEBUG
//定义了,为假
//#define DEBUG 0
//定义了,为真
#define DEBUG 1
int main()
{
#if DEBUGprintf("hello bitworld\n");
#endifreturn 0;
}
//带else的情况
#include <stdio.h>
//报错
//#define DEBUG
//定义了,为假
#define DEBUG 0
//定义了,为真
//#define DEBUG 1
int main()
{
#if DEBUGprintf("hello world\n");
#elseprintf("hello bit\n");
#endifreturn 0;
}
//多条件的情况
//代码一:
#include <stdio.h>
//#define DEBUG 0
//#define DEBUG 1
//#define DEBUG 2
#define DEBUG 3
int main()
{
#if DEBUG==0printf("hello world 0\n");
#elif DEBUG==1printf("hello world 1\n");
#elif DEBUG==2printf("hello world 2\n");
#elseprintf("hello else\n");
#endifreturn 0;//代码二:
#include <stdio.h>
#define DEBUG -1
//#define DEBUG 0
//#define DEBUG 1
//#define DEBUG 2
int main()
{
#if DEBUG<0printf("hello world 0\n");
#elif DEBUG<1printf("hello world 1\n");
#elif DEBUG<2printf("hello world 2\n");
#elseprintf("hello else\n");
#endifreturn 0;
}

#if模拟#ifdef

#include <stdio.h>
#define DEBUG
int main()
{
#if defined(DEBUG)printf("hello debug\n");//这句话会被输出
#elseprintf("hello release\n");
#endifreturn 0;
}

#if模拟#ifndef

#include <stdio.h>
//#define DEBUG
int main()
{
#if !defined(DEBUG)printf("hello debug\n");//这句话会被输出
#elseprintf("hello release\n");
#endifreturn 0;
}

练习

#include <stdio.h>
#define C
#define CPP
int main()
{
#if defined(C) && defined(CPP)//#if (defined(C) && defined(CPP)) //建议使用这种方式printf("hello c&&cpp\n");//这句话会被输出
#elseprintf("hello other\n");
#endifreturn 0;
}

        这段代码使用了条件编译指令,定义了两个宏C和CPP,并且使用#if defined指令判断是否同时定义了这两个宏。

        当同时定义了C和CPP时,程序执行#if defined(C) && defined(CPP)条件满足,会输出"hello c&&cpp"。如果C和CPP没有同时定义,则条件不满足,会输出"hello other"。

在这段代码中,#if defined(C) && defined(CPP)和#if (defined(C) && defined(CPP))的效果是相同的。两者都是判断C和CPP是否都已经被定义了,如果都被定义,则条件满足,执行相应的代码块。

        注意,程序中使用#define指令定义的宏只是简单的文本替换,不会经过类型检查和语法检查。因此在使用宏时需要谨慎,避免出现不必要的错误。

#include <stdio.h>
#define C
//#define CPP
int main()
{
#if defined(C) || defined(CPP)//#if (defined(C) || defined(CPP))printf("hello c||cpp\n");//这句话会被输出
#elseprintf("hello other\n");
#endifreturn 0;
}

        这段代码与前面的稍有不同,它使用#if defined指令判断了C和CPP是否至少有一个被定义了,即#if defined(C) || defined(CPP)。当C和CPP中至少有一个被定义时,条件满足,会输出"hello c || cpp"。否则条件不满足,会输出"hello other"。

        和前面一样,注释掉#define CPP的语句,则只有C被定义,条件不满足,会输出"hello other"。

        需要注意的是,#if defined(C) || defined(CPP)和#if (defined(C) || defined(CPP))的效果也是相同的,这两种写法都是判断C和CPP是否至少有一个被定义了,如果有,则条件满足,执行相应的代码块。

#include <stdio.h>
#define C
#define CPP
int main()
{
#if !(defined(C) || defined(CPP))printf("hello c || cpp\n");//这句话会被输出
#elseprintf("hello other\n");
#endifreturn 0;
}

        这是一个C语言程序,定义了两个宏:C和CPP,并在主函数中使用了#if和#ifndef预编译指令。

        #if !(defined(C) || defined(CPP))表示如果C和CPP中的宏都未定义,则执行if语句内的代码,输出"hello c || cpp"。但是由于C和CPP都被定义了,所以if语句的条件不成立,所以会执行else语句内的代码,输出"hello other"。因此,这个程序的输出结果是"hello other"。

#include <stdio.h>
#define C
#define CPP
int main()
{
#if defined(C)#if defined (CPP)printf("hello CPP\n");//这句话会被输出#endifprintf("hello C\n");//这句话会被输出
#elseprintf("hello other\n");
#endifreturn 0;
}

        这是一个C语言程序,其中使用了条件编译指令。程序定义了两个宏,分别为C和CPP。在main函数中,先判断宏C是否被定义,如果被定义,则进入C语言的条件编译指令中。在这个指令中,又判断宏CPP是否被定义,如果被定义,则输出"hello CPP\n"。无论宏CPP是否被定义,都会输出"hello C\n"。

        如果宏C没有被定义,则程序进入另一个条件编译指令中,输出"hello other\n"。因此,运行该程序,会输出"hello CPP\n"和"hello C\n"。

#include <stdio.h>
#define C
#define CPP
int main()
{
#if defined(C)printf("hello C\n");
#elif defined (CPP)printf("hello CPP\n");
#elseprintf("hello other\n");
#endifreturn 0;
}

        这是一个C语言程序,其中定义了两个宏C和CPP。在main函数中,同样使用了条件编译指令#if-elif-else-endif。在这个指令中,先判断宏C是否被定义,如果被定义,则输出"hello C\n"。如果宏C没有被定义,再判断宏CPP是否被定义,如果被定义,则输出"hello CPP\n"。如果宏C和CPP都没有被定义,则输出"hello other\n"。

        由于宏C和CPP都被定义了,因此运行该程序会输出"hello C\n"。

#if 和 #ifdef的区别

        #if和#ifdef是C预处理中的条件编译指令,它们的作用都是根据某个宏的定义情况来判断编译代码的方式。

        #if的语法形式为#if 常量表达式,它会首先对常量表达式进行求值,如果表达式的值为真,则编译这个#if与对应的#endif之间的代码,否则忽略这个#if与对应的#endif之间的代码。

#ifdef的语法形式为#ifdef 宏名,它用来判断某个宏是否定义了。如果宏被定义了,则编译#ifdef与对应的#endif之间的代码,否则忽略这个#ifdef与对应的#endif之间的代码。

        它们的主要区别在于#if是对表达式的求值结果进行判断,可以进行更加复杂的条件判断,而#ifdef只是判断宏是否被定义,不能进行表达式求值。另外,由于#if可以进行表达式求值,因此在某些情况下,#if比#ifdef会更加灵活和方便。

条件编译和宏替换谁先执行

宏替换先于条件编译执行。

        在C语言中,预处理器会先对源代码进行宏替换,将源代码中的宏名称替换为相应的宏定义,然后再对替换后的代码进行条件编译。也就是说,条件编译是在宏替换之后进行的。这也就意味着,在条件编译中对宏的定义或者值的改变,并不会影响到之前宏替换的结果。

在进行宏替换时,预处理器会根据宏定义中的替换列表来进行替换。如果宏定义中包含了其他宏的调用,那么预处理器会先对这些宏进行替换,然后再对当前宏进行替换。这种替换过程会一直持续下去,直到不包含其他宏的调用为止。

        总的来说,宏替换是在条件编译之前进行的,而且它是一个递归的过程,可以包含其他宏的调用,最终将源代码中的所有宏替换为相应的宏定义后,再对替换后的代码进行条件编译。

条件编译可以用来注释代码吗?推不推荐?

        条件编译可以用来注释代码,但不是最佳实践,因为它会影响到代码的可读性和可维护性。

        在条件编译中,使用了类似于`#if 0 ... #endif`的语句来注释掉代码,它会导致这段代码被编译器忽略掉,从而达到注释的效果。如果这种语句对应的条件值为假,则这段代码将永远不会被编译,从而达到注释掉代码的效果。

        然而,使用条件编译来注释代码会使得代码难以阅读,特别是在复杂的代码环境中。因为代码注释完全可以通过标准注释语法来实现,这样会更加清晰易懂,也更易于维护。而使用条件编译来注释代码,会给读代码的人带来很大的困扰,因为他们不得不去寻找代码中存在的所有条件编译语句,以了解到底有哪些代码是被注释掉的。

        因此,推荐使用标准注释语法来进行注释,并尽可能避免使用条件编译来注释掉代码。这样会使代码更具可读性和可维护性。

结论:条件编译本质是让编译器进行代码裁剪。

2.为何要有条件编译?

3. 条件编译都在哪些地方用?


http://www.ppmy.cn/news/92602.html

相关文章

AI 工具分享第 4 期:13 款国外免费AI视频生成工具

0. 未来百科 未来百科&#xff0c;是一个知名的AI产品导航网站 —— 为发现全球优质AI工具而生 。目前已 聚集全球3000优质AI工具产品 &#xff0c;旨在帮助用户发现全球最好的AI工具&#xff0c;同时为研发AI垂直应用的创业公司提供展示窗口&#xff0c;迎接未来的AI时代。未来…

3D点云深度学习处理的基本概念

权重矩阵更新学习方法概述 参数初始化&#xff1a; 需要对权重矩阵初始化参数&#xff08;通常使用随机初始化方法&#xff0c;如正态分布或者均匀分布生成随机数&#xff09; 前向传播&#xff1a; 前向传播中&#xff0c;模型计算权重矩阵和输入数据的结果&#xff0c;得…

streamlit部署显示pyecharts交互图表

文章目录 pyecharts简介pyecharts版本安装方式streamlit pyecharts柱状图折线图饼图词云图map地图streamlit app 展示全部代码pyecharts简介 pyecharts 是一个用于生成 Echarts 图表的类库。Echarts 是百度开源的一个数据可视化 JS 库。用 Echarts 生成的图可视化效果非常棒,…

[论文分享] When deep learning met code search

When deep learning met code search [ESEC/FSE 2019] Jos Cambronero MIT CSAIL U.S.A. Hongyu Li Facebook, Inc. U.S.A. SeohyunKim Facebook,Inc. U.S.A. KoushikSen EECSDepartment,UCBerkeley U.S.A. SatishChandra Facebook,Inc. U.S.A. 最近有多个关于使用深度神经网…

python 基于 sqlite 实现消息队列

文章大纲 背景基于sqlite 的内存数据库性能指标可参考的开源库 与实现方案基于sqlite 的方案基于 AMQP 的方案参考文献与学习路径背景 假如我要在内网、安全等级限制、无法安装第三方软件,如redis 等的环境下搭建一个开源的机器学习系统,给一些实时生成的数据、图片等进行异…

【Python】列表和字典

知识目录 一、写在前面✨二、列表应用三、字典应用四、总结撒花&#x1f60a; 一、写在前面✨ 大家好&#xff01;我是初心&#xff0c;希望我们一路走来能坚守初心&#xff01; 今天跟大家分享的文章是 Python函数式编程第二弹&#xff0c;再次以两个简单的例子带大家更好的…

园区网络安全设计——出口防火墙

园区网络安全设计——出口防火墙 网络接入人员众多&#xff0c;业务复杂&#xff0c;流量构成丰富多样&#xff1b;容易成为DDoS攻击的目标&#xff0c;而且一旦攻击成功&#xff0c;业务损失巨大&#xff1b;网络病毒活跃&#xff0c;严重威胁网络安全和终端的安全&#xff1…

同余方程 乘法逆元 扩展欧几里得算法 5.26

同余方程 乘法逆元 扩展欧几里得算法 526 同余方程 乘法逆元 扩展欧几里得算法_哔哩哔哩_bilibili 给定整数a,b,m&#xff0c;求解同余方程axb(mod m). 如果x存在整数解&#xff0c;则输出任意一个&#xff1b; 如果不存在&#xff0c;则输出none 例&#xff1a; 8x4(mod…