浅谈 C/C++ 的条件编译

2023-11-04

1.条件编译的时机

我们都知道vscode其实是一个编辑器,你要在上面跑C或者C++你需要配置编译器,拿编译器是怎样吧一个文本文件变成一个可执行文件的呢?

那必然是经历以下这四步

  1. 预处理:宏替换,头文件的展开,去注释,条件编译
  2. 编译:将预处理后的源文件转换为汇编语言文件,只编译源文件,不编译头文件,头文件在刚刚预处理阶段已经展开。
  3. 汇编:虽然叫做汇编,但是不是转变为汇编代码,而是将刚刚的汇编语言文件转换为机器码,也就是二进制文件。
  4. 链接:将生成的二进制代码与库函数以及其他目标文件,通过链接器链接起来形成可执行文件的过程。

分析了以上过程由此可以很清晰的得出这个结论,条件编译是在预处理的时候发生的。

2.条件编译的作用

条件编译是指预处理的时候根据条件编译的指令有条件的选择源程序中的一部分代码送给编译器进行编译,进行有选择性的操作,防止宏替换的内容重复包含。

常见的条件编译指令如下:

常见条件编译指令
条件编译指令                                        操作
       #if 如果条件为真则执行相应操作
      #elif 如果前面条件为假,而该条件为真,则执行相应操作
     #else 如果前面条件均为假,则执行相应操作
     #endif 结束相应的条件编译指令
     #ifdef 如果该宏已定义,则执行相应操作
     #ifndef 如果该宏没有定义,则执行相应操作

3.#if   #else   #endif

#if 表达式

// code

#else

// code

#endif

如果表达式为真则#if后程序段被调用

明显发现第一段的色段跟第二段的色段都不一样!肯定是第一句输出了!

 可以看到他直接call调用的就是标准命名空间下的operator类里面的函数,其实也就是 << 输出

4.#ifndef   #define   #endif

#ifdef 标识符
#define 标识符 替换列表

// code

#endef 
  1. 一般用于检测程序中是否已经定义了名字为某标识符的宏,如果没有定义该宏,则定义该宏,并选中从 #define 开始到 #endif 之间的程序段;
  2. 如果已定义,则不再重复定义该符号,且相应程序段不被选中。

我们都知道NULL在C中是一个宏,宏有时也会引起不必要的问题在C++11中则有了nullptr,所以这块显示是已经被宏过了,所有不执行#define 到#endef的程序段所以看起来是灰色的。

 

 

红色框框是每个函数都有的,就是主函数栈帧开辟和销毁的过程,再看中间好家伙啥都没有,再次印证了,我们说的 如果没有定义该宏,则定义该宏,并选中从 #define 开始到 #endif 之间的程序段;如果已定义,则不再重复定义该符号,且相应程序段不被选中。

该条件编译指令更重要的一个应用是防止头文件重复包含。

如果 f.c 源文件中包含 f1.h 和 f2.h 两个头文件,而 f1.h 头文件及 f2.h 头文件中均包含 f3.h 头文件,则 f.c 源文件因为包含了 f1.h 和 f2.h 两个头文件,所以中重复包含 f3.h 头文件。可采用条件编译指令,来避免头文件的重复包含问题。

#ifndef _HEADNAME_H_

#define _HEADNAME_H_

    //头文件内容

#endif
  1. 当该头文件第一次被包含时,由于没检测到该头文件名对应的宏名,则定义该头文件名对应的宏,其值为该系统默认。并且,该条件编译指令选中 #endif 之前的头文件内容;
  2. 如果该头文件再次被包含时,由于检测到已存在以该头文件名对应的宏名,则忽略该条件编译指令之间的所有代码,从而避免了重复包含。

5.#if   #elif   #else   #endif

#if 条件表达式1

    // code1

#elif 条件表达式2

    //code 2

#else
        
    //code 3

#endif
  1.  功能为:先判断条件1的值,如果为真,则程序段 1 被选中编译;
  2. 如果为假,而条件表达式 2 的值为真,则程序段 2 被选中编译;
  3. 其他情况,程序段 3 被选中编译。

 6.#ifdef   #endif

#ifdef 标识符
    
    //code

#endif
  1. 如果检测到已定义该标识符,则选择执行相应程序段被选中编译;
  2. 否则,该程序段会被忽略。
#include <iostream>
using namespace std;
#define PI 3.14
int main() {
#ifdef PI 
#undef PI
	cout << "PI 已经被取消宏" << endl;
#endif 
}

如果检测到符号 PI 已定义,则删除其定义,并选中相应的程序段。

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

浅谈 C/C++ 的条件编译 的相关文章

  • 部署 MVC4 项目时出错:找不到文件或程序集

    过去 我只需使用 Visual Studio 2012 发布到 AWS 菜单项即可部署我的 MVC4 网站 到 AWS Elastic Beanstalk 现在 程序可以在本地编译并运行 但无法部署 从消息来看 它似乎正在寻找不在当前部署的
  • boost::multi_index_container 复合键中的 equal_range 与比较运算符

    我正在尝试从多索引容器查询结果 其中值类型是三个元素的结构 第一个值已给出 但第二个和第三个值必须大于或小于查询参数 经过搜索后 我发现必须实现自定义密钥提取器 并且这里的一些链接建议相同 但我无法实现它 boost multi index
  • 在 LINQ 查询中返回不带时间的日期

    我正在编写一个查询 我想计算按日期联系我们的呼叫中心的次数 看起来很简单 但由于联系日期字段是日期时间字段 我得到了时间 因此当我按联系日期 时间 分组时 每个联系日期实例的计数为 1 所以 我想只按日期分组 而不按时间分组 下面是我用来查
  • 如何在 Unity 中从 RenderTexture 访问原始数据

    问题的简短版本 我正在尝试访问 Unity 中 RenderTexture 的内容 我一直在使用 Graphics Blit 使用自己的材质进行绘制 Graphics Blit null renderTexture material 我的材
  • 在 Xamarin Android 中将图像从 URL 异步加载到 ImageView 中

    我有一个包含多个项目的 ListView 列表中的每个项目都应该有一个与之关联的图像 我创建了一个数组适配器来保存每个列表项并具有我希望加载的图像的 url 我正在尝试使用 Web 请求异步加载图像 并设置图像并在加载后在视图中更新它 但视
  • 使用 Microsoft Graph API 订阅 Outlook 推送通知时出现 400 错误请求错误

    我正在尝试使用 Microsoft Graph API 创建订阅以通过推送通知获取 Outlook 电子邮件 mentions 我在用本文档 https learn microsoft com en us graph api subscri
  • C# 用数组封送结构体

    假设我有一个类似于 public struct MyStruct public float a 我想用一些自定义数组大小实例化一个这样的结构 在本例中假设为 2 然后我将其封送到字节数组中 MyStruct s new MyStruct s
  • c# Asp.NET MVC 使用FileStreamResult下载excel文件

    我需要构建一个方法 它将接收模型 从中构建excel 构建和接收部分完成没有问题 然后使用内存流导出 让用户下载它 不将其保存在服务器上 我是 ASP NET 和 MVC 的新手 所以我找到了指南并将其构建为教程项目 public File
  • .Net Core / 控制台应用程序 / 配置 / XML

    我第一次尝试使用新的 ConfigurationBuilder 和选项模式进入 Net Core 库 这里有很多很好的例子 https docs asp net en latest fundamentals configuration ht
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • 线程、进程和 Application.Exit()

    我的应用程序由主消息循环 GUI 和线程 Task Factory 组成 在线程中我调用一些第三方应用程序var p new Process 但是当我调用Application Exit 在消息循环中 我可以看到在线程中启动的进程仍在内存中
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • 更改窗口的内容 (WPF)

    我创建了一个简单的 WPF 应用程序 它有两个 Windows 用户在第一个窗口中填写一些信息 然后单击 确定 这会将他们带到第二个窗口 这工作正常 但我试图将两个窗口合并到一个窗口中 这样只是内容发生了变化 我设法找到了这个更改窗口内容时
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • 方法参数内的变量赋值

    我刚刚发现 通过发现错误 你可以这样做 string s 3 int i int TryParse s hello out i returns false 使用赋值的返回值是否合法 Obviously i is but is this th
  • 如何将字符串“07:35”(HH:MM) 转换为 TimeSpan

    我想知道是否有办法将 24 小时时间格式的字符串转换为 TimeSpan 现在我有一种 旧时尚风格 string stringTime 07 35 string values stringTime Split TimeSpan ts new
  • 不同类型的指针可以互相分配吗?

    考虑到 T1 p1 T2 p2 我们可以将 p1 分配给 p2 或反之亦然吗 如果是这样 是否可以不使用强制转换来完成 或者我们必须使用强制转换 首先 让我们考虑不进行强制转换的分配 C 2018 6 5 16 1 1 列出了简单赋值的约束

随机推荐

  • MySQL数据库连接超时自动断开的解决方案

    一次朋友小聚 大家谈起了技术问题 一个在国企里的同学说 他们的系统很奇怪 每天早上都得重启一下应用程序 否则就提示连接数据库失败 他们都不知道该怎么办 我当时稍加思索说了一下 应该是连接超时引起的 这样的问题在我的业务场景没有遇到过 所以我
  • 三菱服务器显示代码d2,三菱QD64D2手册QD64D2用户手册 - 广州凌控

    SRAM E2PROM存储卡 RAM容量 64KB E2PROM容量 64KB 输入输出点数 4096点 输入输出元件数 8192点 程序容量 1000 k步QD64D2用户手册 处理速度 0 0095 s 程序存储器容量 4000 KB
  • Java--SpringMVC之处理器方法返回值

    一 处理器方法返回值 使用 Controller注解的处理器方法 返回值会有四种类型 ModelAndView String Void 自定义Java对象 1 ModelAndView ModelAndView 有数据和视图 若处理器方法处
  • python如何安装第三方库 request_python 安装第三方库 request时报错

    今天安装request时报错 F pythonFile gt pip install requests Collecting requests Downloading requests 2 24 0 py2 py3 none any whl
  • 饼图 echarts -无数据时给提示

    div class thirdEchartBody div mport pieGenderChartConfig from js passengerFlowAnalysisConfig js mounted this getGenderCh
  • 永别了gitee图床,阿里云图床我来啦!!!

    文章目录 缘由 前期准备工作一 下载了 Typora 和Picgo 1 本人 Typora 版本 2 本人Picgo 版本 准备工作二 注册阿里云账号 重要 一定要看一下 步骤一 点击控制台 步骤二 选择 对象储存 并开通 步骤三 点击左侧
  • javascript 大文件下载,分片下载,断点续传

    javascript 大文件下载 分片下载 断点续传 文章目录 javascript 大文件下载 分片下载 断点续传 1 获取文件大小 2 切片下载 3 合并数据 4 下载到本地 5 成功 6 完整代码 既然是断点续传 自然离不开分片下载
  • 小程序自动更换标题文字及icon的方法

    一 动态生成底部tabBar的icon和文字 wx setTabBarItem index 2 text 商品 iconPath assets StoreLife 2x png selectedIconPath assets storeLi
  • 关于Mysql的驱动(org.gjt.mm.mysql.Driver)问题

    目前我知道的连接mysql的驱动有两个 一个是org gjt mm mysql Driver 另外一个是com mysql jdbc Driver 我做毕设时使用的org gjt mm mysql Driver 这个比较老了 现在使用的比较
  • QT VS与QT的项目配置

    VS中添加Qt模块 VS中添加Qt文件
  • 单端、差分、伪差分输入

    单端信号 单端信号 single end 是相对于差分信号而言的 单端输入指信号有一个参考端和一个信号端构成 参考端一般为地端 ADC单端输入 比如说UART232串口中 发送端TXD 接收端RXD 参考端是地 GND 是典型的单端信号输入
  • 对象相等比较

    String的相等比较 对于String类型而言 一般用 或者equales做相等比较 前者比较字符串的引用 后者比较字符串的值 字符串常量的值存储于常量池中 只要值相同 那么引用的就是同一个字符串常量 也就是说 和equals效果一样 字
  • faster rcnn 训练自己的数据集---踩坑记录!!!

    下载代码 git clone https github com jwyang faster rcnn pytorch git 也可以暴力下载 直接download压缩包 2 解压完 cd到faser rcnn pytorch文件夹中 再创建
  • C++快速排序和一些细节思考

    一 原理 选一个基准数 通常选需要排序数组的第一个元素 将该基准数从两端开始比较 找到从左边起比此基数大的数 从右边起比此基数小的数 然后交换两数 两端相遇后一轮截止 相遇的位置就是基准数的正确位置 且基准数左边都小于此基准数 右边都大于此
  • 固高运动控制卡QT和VS(MFC)的配置

    一 QT配置 第一步 将需要的文件保存在项目下 gts h gts dll gts lib 第二步 将 gts h 加入项目 第三步 在pro文件中添加 lib文件 添加外部库后 代码为 如果不对自己导入外部库即可 win32 LIBS L
  • 【RuoYi-Vue-Plus】问题笔记 07 - V3.5.0 Redisson 报错 Unable to send PING command over channel

    文章目录 前言 参考目录 问题说明 问题解决方法 前言 最近找了一下终于解决了 Redisson 的 RedisTimeoutException 报错问题 在此记录一下 参考目录 Redisson Issues 3273 Redisson
  • 浩辰CAD 2021:深度升级,全面提升用户体验!

    在全球新冠疫情背景下 全球经济发展速度明显减缓 国内国外的市场竞争更加激烈 各企业对于提升数字化 网络化 智能化发展水平的需求也愈发迫切 这就需要企业配备更加全面和系统化的数字化设计平台 提高创新研发能力和市场竞争力 快速响应市场需求 把握
  • UnityVR--机械臂场景4-礼物和圣诞树

    本文场景中被抓取的物体是礼物 使用机械臂抓取礼物 将礼物放置在圣诞树的某个位置 来装饰圣诞树 1 礼物的设置 礼物必须具备Collider和Rigidbody 因为需要手爪放开后 礼物会自由掉落的效果 还要将礼物设置为 Goods 的标签
  • 十句话,不黄不色,但很经典~~~~~~~~~~

    1 如果钱还宽裕 别养二奶 偷偷养几个贫困山区的学生 别让人家知道你是谁 要不然见面了多尴尬 多不好意思 但是你心里一定会觉得舒坦 比包二奶提心吊胆的要好得多 如果真想包也可以包一个 好事坏事一起做 人吗 本来就复杂 2 遇到夜里摆地摊的
  • 浅谈 C/C++ 的条件编译

    1 条件编译的时机 我们都知道vscode其实是一个编辑器 你要在上面跑C或者C 你需要配置编译器 拿编译器是怎样吧一个文本文件变成一个可执行文件的呢 那必然是经历以下这四步 预处理 宏替换 头文件的展开 去注释 条件编译 编译 将预处理后