C++ 编译预处理
在编译器对源程序进行编译时,首先要由处理器对程序文本进行预处理。预处理器提供了一组编译预处理指令和预处理操作符。预处理指令实际上不是C++语言的一部分,它只是用来扩充C++程序设计环境。所有的预处理指令在程序中都以“#”来引导,每一条预处理指令单独占用一行,不要用分号结束。预处理指令可以根据需要出现在程序中的任何位置。
1. #include指令
#include指令也称文件包含指令,其作用是将另一源文件嵌入到当前源文件中该点处。通常用#include指令来嵌入头文件。文件包含指令有如下两种格式:
(1)#include<文件名>
按标准方式搜索,文件位于系统目录的include子目录下。
(2)#include"文件名"
首先在当前目录中搜索,若没有,再按标准方式搜索。
#include指令可以嵌套使用。假设有一个头文件myhead.h,该头文件中又可以有如下的文件包含指令:
#include"file1.h"
#include"file2.h"
2. #define指令和#undef指令
预处理器最初是为C语言设计的,#define曾经在C程序中被广泛使用,因为#define可以完成的一些功能能够被C++引入的一些语言特性很好地替代。
在C语言中,用#define来定义符号常量,例如下面预编译指令定义了一个符号常量PI的值为3.14:
#define PI 3.14
在C++中虽然仍然可以这样定义符号常量,但是更好的方法是在类型说明语句中用const修饰。
在C语言中,还可以用#define来定义带参数宏,以实现简单的函数计算,提高程序的运行效率,但是在C++中这一功能已被内联函数取代。
#define还可以定义空符号,例如:
#define MYHEAD_H
定义它的目的,仅仅表示“MYHEAD_H已经定义过”这样一种状态。将该符号配合条件编译指令一起使用,可以起到一些特殊作用,这是C++程序中#define的最常用之处。
#undef的作用是删除由#define定义的宏,使之不再起作用。
3. 条件编译指令
使用条件编译指令,可以限定程序中的某些内容要在满足一定条件的情况下才参与编译。因此,利用条件编译指令可以使同一个源程序在不同的编译条件下产生不同的目标代码。例如,可以在调试程序时增加一些调试语句,以达到跟踪目的,并利用条件编译指令,限定当程序调试好以后,重新编译时,使调试语句不参与编译。常用的条件编译语句有:
(1)形式1:
#if 常量表达式程序段 //当常量表达式为非0时编译本程序段
#endif
(2)形式2:
#if 常量表达式程序段1 //当常量表达式为非0时编译本程序段
#else程序段2 //当常量表达式为0时编译本程序段
#endif
(3)形式3:
#if 常量表达式1程序段1 //当常量表达式1为非0时编译本程序段
#elif 常量表达式2程序段2 //当常量表达式1为0、常量表达式2为非0时编译本程序段...
#elif 常量表达式n程序段n //当常量表达式1...常量表达式n-1均为0//常量表达式n不为0时编译本程序段
#else程序段n+1 //其他情况下编译本程序段
#endif
(4)形式4:
#ifdef 标识符程序段1
#else程序段2
#endif
如果“标识符”经#define定义过,且未经#undef删除,则编译程序段1,否则编译程序段2。如果没有程序段2,则#else可以省略:
#ifdef 标识符程序段1
#endif
(5)形式5:
#ifndef 标识符程序段1
#else程序段2
#endif
如果“标识符”未被定义,则编译程序段1,否则编译程序段2。如果没有程序段2,则#else可以省略:
#ifndef 标识符程序段1
#endif
4. defined操作符
defined是一个预处理操作符,而不是指令,因此不要以#开头。defined操作符使用的形式为:
defined(标识符)
若“标识符”在此前经#define定义过,并且未经#undef删除,则上述表达式为非0,否则上述表达式的值为0。
下面两种写法完全等效:
#ifndef MYHEAD_H
#define MYHEAD_H...
#endif
等价于:
#if!defined(MYHEAD_H)
#define MYHEAD_H...
#endif
由于文件包含指令可以嵌套使用,在设计程序时要避免多次重复包含同一个头文件,否则会引起变量及类的重定义。例如,某个工程包括如下4个源文件:
main.cpp:
#include"file1.h"
#include"file2.h"
int main()
{...
}
file1.h:
#include"head.h"
...
file2.h:
#include"head.h"
...
head.h:
class Point
{};
这时,由于#include指令的嵌套使用,使得头文件head.h被包含了两次,于是编译时系统会出错:Point类被重复定义。如何避免这种情况呢?
这就是要在可能被重复包含的头文件中使用条件编译指令。用一个唯一的标识符来标记某文件是否已参加过编译,如果已参加过编译,则说明该程序段是被重复包含的,编译时忽略重复部分。将文件head.h改写如下:
#ifndef HEAD_H
#define HEAD_H
class Point
{};
#endif
在这个头文件中,首先判断标识符HEAD_H是否被定义过。若未定义过,说明此头文件尚未参加过编译,于是编译下面的程序段,并且对标识符HEAD_H进行宏定义,标记此文件已参加过编译。若标识符HEAD_H被定义过,说明此头文件参加过编译,于是编译器忽略下面的程序段。这样就不会造成对Point的重复定义。
相关文章:
C++ 编译预处理
在编译器对源程序进行编译时,首先要由处理器对程序文本进行预处理。预处理器提供了一组编译预处理指令和预处理操作符。预处理指令实际上不是C语言的一部分,它只是用来扩充C程序设计环境。所有的预处理指令在程序中都以“#”来引导,每一条预处…...
备战秋招 | 笔试强化22
目录 一、选择题 二、编程题 三、选择题题解 四、编程题题解 一、选择题 1、在有序双向链表中定位删除一个元素的平均时间复杂度为 A. O(1) B. O(N) C. O(logN) D. O(N*logN) 2、在一个以 h 为头指针的单循环链表中,p 指针指向链尾结点的条件是( ) A. p->ne…...
LeetCode ACM模式——哈希表篇(二)
刷题顺序及思路来源于代码随想录,网站地址:https://programmercarl.com 202. 快乐数 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。然后重复…...
hadoop 3.1.3集群搭建 ubuntu20
相关 hyper-v安装ubuntu-20-server hyper-v建立快照 hyper-v快速创建虚拟机-导入导出虚拟机 准备 虚拟机设置 采用hyper-v方式安装ubuntu-20虚拟机和koolshare hostnameiph01192.168.66.20h02192.168.66.21h03192.168.66.22 静态IP 所有机器都需要按需设置 sudo vim /e…...
备忘录模式——撤销功能的实现
1、简介 1.1、概述 备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤。当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原。当前很多软件都提供了撤销(Undo)操作…...
Golang 函数参数的传递方式 值传递,引用传递
基本介绍 我们在讲解函数注意事项和使用细节时,已经讲过值类型和引用类型了,这里我们再系统总结一下,因为这是重难点,值类型参数默认就是值传递,而引用类型参数默认就是引用传递。 两种传递方式(函数默认都…...
K8s影响Pod调度和Deployment
5.应用升级回滚和弹性伸缩...
透明代理和不透明代理
透明代理和不透明代理 1、透明代理(Transparent Proxy)2、不透明代理(Non-Transparent Proxy)3、工作原理4、透明代理为啥比不透明代理多一部先连接到路由再到代理服务器?5、这里路由器做了什么工作6、代理自动配置文件(Proxy Auto-Configuration file,PAC file)7、代理…...
1424. 对角线遍历 II;2369. 检查数组是否存在有效划分;1129. 颜色交替的最短路径
1424. 对角线遍历 II 核心思想:我感觉是一个技巧题,如果想到很容易做出了,想不到就很难了。首先对于一条对角线的数,其坐标ij是一样的,然后同一条对角线斜向上的j是从小到大的,知道这个就很容易做出来了。…...
【漏洞复现】Metabase 远程命令执行漏洞(CVE-2023-38646)
文章目录 前言声明一、漏洞介绍二、影响版本三、漏洞原理四、漏洞复现五、修复建议 前言 Metabase 0.46.6.1之前版本和Metabase Enterprise 1.46.6.1之前版本存在安全漏洞,未经身份认证的远程攻击者利用该漏洞可以在服务器上以运行 Metabase 服务器的权限执行任意命…...
Linux 9的repo for OVS build
源码中自带RPM包spec文件 cd /root/rpmbuild/SOURCES/openvswitch-2.17.7/rhel rpmbuild -bb openvswitch.spec ## 按提示解决,不好解决的依赖可以试试下面的repo 方法 error: File /root/rpmbuild/SOURCES/openvswitch-2.17.7.tar.gz: No such file or direct…...
DOCTYPE 是什么作用?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ DOCTYPE 是什么作用?⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴…...
KubeSphere 3.4.0 发布:支持 K8s v1.26
2023 年 07 月 26 日,KubeSphere 开源社区激动地向大家宣布,KubeSphere 3.4.0 正式发布! 让我们先简单回顾下之前三个大版本的主要变化: KubeSphere 3.1.0 新增了“边缘计算”、“计量计费” 等功能,将 Kubernetes 从…...
自然语言文本分类模型代码
以下是一个基于PyTorch的文本分类模型的示例代码,用于将给定的文本分为多个预定义类别: import torch import torch.nn as nn import torch.nn.functional as Fclass TextClassifier(nn.Module):def __init__(self, vocab_size, embedding_dim, hidden_…...
Prometheus实现系统监控报警邮件
Prometheus实现系统监控报警邮件 简介 Prometheus将数据采集和报警分成了两个模块。报警规则配置在Prometheus Servers上, 然后发送报警信息到AlertManger,然后我们的AlertManager就来管理这些报警信息,聚合报警信息过后通过email、PagerDu…...
could not import go.etcd.io/etcd/clientv3-go
问题描述 今天在封装etcd的时候导包报错: could not import go.etcd.io/etcd/clientv3 (no required module provides package "go.etcd.io/etcd/clientv3") 问题解决: get:确保下载了client包 go get go.etcd.io/etcd/client tidy go mod tidy 本文由 mdnice 多平台…...
MySQL的行锁、表锁触发
MySQL的行锁、表锁触发 sql CREATE TABLE products ( product_id INT PRIMARY KEY, product_name VARCHAR(50), stock INT ); INSERT INTO products (product_id, product_name, stock) VALUES (1001, ‘商品A’, 50), (1002, ‘商品B’, 30), (1003, ‘商品C’, 20); 一、行锁…...
mysql-入门笔记-3
# ----------排序查询-------- # 语法 # select 字段列表 from 表名 order by 字段1 排序方式1 ,字段2 排序方式2 ; DESC 降序 ASC升序 # 1 根据年龄对公司的员工进行升序排序---默认升序-黄色提示代码冗余 select * from userTable order by age ASC ; # 2 根据入职时间,对员…...
3分钟创建超实用的中小学新生录取查询系统,现在可以实现了
在新学期开始之际,作为招生负责人,您是否已经做好准备来迎接新学年的招生工作呢?录取新生所需的任务包括录入成绩信息、核对招生要求以及公布新生录取信息等,这些工作繁重而具有挑战性,给负责招生的老师带来了巨大的压…...
Redis 变慢了 解决方案
一、Redis为什么变慢了 1.Redis真的变慢了吗? 对 Redis 进行基准性能测试 例如,我的机器配置比较低,当延迟为 2ms 时,我就认为 Redis 变慢了,但是如果你的硬件配置比较高,那么在你的运行环境下ÿ…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...
系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...
