预处理指令

1.预定义符号

预定义符号是在预处理阶段处理的。

1.__FILE__ // 进⾏编译的源⽂件
2.__LINE__ // ⽂件当前的⾏号
3.__DATE__ // ⽂件被编译的⽇期
4.__TIME__ // ⽂件被编译的时间
5.__STDC__ // 如果编译器遵循 ANSI C ,其值为 1 ,否则未定义
由于vs2022未完全使用ANSI C所以__STDC__未定义

2.#define 定义常量

# define name stuff
我们在前面定义宏的时候好像都没有加上; ,这是为什么呢?
因为宏定义在展开的时候回直接替换原来位置的内容,所以如果定义的时候加上分号会容易导致问题
由于if没加代码块,它只能直接匹配一段代码,而这里有两个分号,也就是两个语句,导致后面的else不知道跟谁匹配。

3.#define定义宏

define定义宏和定义常量的区别就是定义宏有参数,这种实现通常称为宏(macro)或定义宏

(define macro)。

宏的申明方式:

# define name( parament-list ) stuff
注意:()必须与name紧挨着,否则他会直接替换为后面的内容。
比如我们要写一个乘法的宏:
但是这样写会存在一些问题:
我们期望的是4*6得到24,可是实际写过确实9 。这也是宏替换的规则导致的,实际算的是3+1*5+1=9
结论:定义宏的时候不要吝啬括号

4.带有副作用的宏参数

带有副作用的宏参数比如++ --操作符,在参数数量超过1个时会导致问题

比如:

这里得到的是7 4 6 也是因为宏的处理是替换而不是函数的先计算再传值。

这里经过预处理后:

(x++) > (y++) ? (x++) : (y++);

5.宏替换的规则

1.在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先

被替换。
这里就是在替换MAX的时候检查到里面还有一个NUM宏,先对NUM进行替换
2. 替换文本随后被插⼊到程序中原来文本的位置。对于宏,参数名被他们的值所替换。

3.最后,再次对结果⽂件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上

述处理过程。
注意:
1. 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。

2.当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。

6.宏和函数的对比

两个求最大值的方法对比下,宏的方法更好一点:

1.宏的处理只涉及到计算,而函数涉及到函数的调用、计算、函数的返回。因此函数的时间开销大一点

2.宏的替换原则并没有参数限制,而函数针对于不同的参数要写不同的版本。

函数的优势:

1.每次使⽤宏的时候,⼀份宏定义的代码将插⼊到程序中。除非宏比较短,否则可能大幅度增加程序的长度。
2. 宏是没法调试的。
3. 宏由于类型无关,也就不够严谨。
4. 宏可能会带来运算符优先级的问题,导致程容易出现错。
宏有时候可以做函数做不到的事情。比如:宏的参数可以出现类型,但是函数做不到。
下面我们用malloc举例:
函数和宏的对比:

7.#和##

#运算符

#并不是#include或者#define的#

#运算符将宏的⼀个参数转换为字符串字面量。它仅允许出现在带参数的宏的替换列表中。
#运算符所执行的操作可以理解为”字符串化“。
比如我们要写下面一段代码:
我们发现这个打印功能可以抽象出来一个宏:

## 运算符

## 可以把位于它两边的符号合成⼀个符号,它允许宏定义从分离的文本片段创建标识符。
## 被称为记号粘合 这样的连接必须产生⼀个合法的标识符。否则其结果就是未定义的
比如我们要定义一个宏来写不同类型数据求最大值得函数:

8.命名约定

由于宏和函数的相似性,所以为了区分它们两个,一般的:

宏的字母全部大写

函数一般是首字母大写

9.#undef

当我们定义的宏在某时段不用了或者需要重定义,那么这就需要把原有的定义取消掉。

这就需要用到#undef

10.命令行定义

假设我们的代码要根据不同的机器设置不同的版本,就像前面的位段一样,就要用的命令行代码

这里简单的拿一个数组大小举例:

我们并在写的时候并不直接将ARRAY_SIZE定义。而是在使用的时候给一个大小。

//linux 环境演示。
gcc -D ARRAY_SIZE= 10 programe.c

11.条件编译

条件编译顾名思义就是看情况编译,这跟if语句很像,但是它们的处理阶段不同,一个是在预处理阶段,一个是运行阶段。

比如我们在编译的时候需要有调试语句,但是不用的时候删掉再写一遍又很麻烦,所以我们选择性编译:

常见的形式:

1.

#if 常量表达式

//...

#endif

2.多分支条件的编译

#if 常量表达式

//...

#elif 常量表达式

//...

#else

//...

#endif

3.判断是否被定义

#if defined(symbol)

#ifdef symbol

#if !defined(symbol)

#ifndef symbol

4.嵌套指令
#if defined(OS_UNIX)
#ifdef OPTION1
unix_version_option1();
#endif
#ifdef OPTION2
unix_version_option2();
#endif
#elif defined(OS_MSDOS)
#ifdef OPTION2
msdos_version_option2();
#endif
#endif

12.头文件的包含

头文件有两种包含方式:

1.本地头文件包含

包含方式:

先从自己所在的路径搜索,如果没有就在存放标准库的文件中搜索。

2.库函数的头文件包含

包含方式:

直接从存放标准库的文件中搜索。

3.嵌套文件包含

像这样的多次包含是会出现的,而且编译器在预处理的时候也会真的把他们都拷过来。

如何避免呢?

条件编译。
完。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/479651.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 12.0新增自定义HIDL问题记录

代码 流程和代码可以参考这位大佬的 https://blog.csdn.net/learnframework/article/details/134621556 主要记录发现的问题以及解决方式。 1.首先最外层的bp不要使用update-makefiles.sh 去生成 ,基本上interface下面的文件夹都会被影响,可能会导致编…

(即插即用模块-Attention部分) 二十、(2021) GAA 门控轴向注意力

文章目录 1、Gated Axial-Attention2、代码实现 paper:Medical Transformer: Gated Axial-Attention for Medical Image Segmentation Code:https://github.com/jeya-maria-jose/Medical-Transformer 1、Gated Axial-Attention 论文首先分析了 ViTs 在训…

[C++ 核心编程]笔记 4.1 封装

4.1.1 封装的意义 封装是C面向对象三大特性之一 封装的意义: 将属性和行为作为一个整体,表现生活中的事物将属性和行为加以权限控制 封装意义一: 在设计类的时候,属性和行为写在一起,表现事物 语法: class 类名{ 访问权限: 属性 /行为 }…

韩顺平 一周学会Linux | Linux 实操篇-组管理和权限管理

一、Linux 组 1. 组基本介绍 在linux 中的每个用户必须属于一个组,不能独立于组外。在linux 中每个文件有所有者、所在组、其它组的概念。 2. 文件/目录 所有者 一般为文件的创建者,谁创建了该文件,就自然的成为该文件的所有者。 1) 查看文件所有者&…

FBX福币交易所创业板指放量大涨2.73% 谷子经济概念持续爆发

查查配分析11月27日电 27日,A股三大指数探底回升,沪指涨逾1%,创业板指涨近3%。全市成交额较上个交易日放量至1.49万亿元。 截至收盘,上证指数涨1.53%,报3309.78点;深证成指涨2.25%,报10566.10点;创业板指涨2.73%,报2208.78点。 FBX福币凭借用户友好的界面和对透明度的承诺,迅速…

前端性能优化之任务管理/调度

浏览器的一帧 前面我们提到如何使用requestAnimationFrame来检测是否产生了卡顿。除此之外,如果你也处理过简单的异步任务管理(闲时执行等),还可以使用requestIdleCallback来检测卡顿。其实,requestAnimationFrame和requestIdleCallback都会在浏览器的每一帧中被执行到,…

Ubuntu20.04安装kalibr

文章目录 环境配置安装wxPython下载编译测试报错1问题描述问题分析问题解决 参考 环境配置 Ubuntu20.04,python3.8.10,boost自带的1.71 sudo apt update sudo apt-get install python3-setuptools python3-rosinstall ipython3 libeigen3-dev libboost…

QUAD-MxFE平台

QUAD-MxFE平台 16Tx/16Rx直接L/S/C频段采样相控阵/雷达/电子战/卫星通信开发平台 概览 优势和特点 四通道MxFE数字化处理卡 使用MxFE的多通道、宽带系统开发平台 与Xilinx VCU118评估板(不包括)搭配使用 16个RF接收(Rx)通道(32个数字Rx通道…

互联网视频推拉流EasyDSS视频直播点播平台视频转码有哪些技术特点和应用?

视频转码本质上是一个先解码再编码的过程。在转码过程中,原始视频码流首先被解码成原始图像数据,然后再根据目标编码标准、分辨率、帧率、码率等参数重新进行编码。这样,转换前后的码流可能遵循相同的视频编码标准,也可能不遵循。…

开源加密库mbedtls及其Windows编译库

目录 1 项目简介 2 功能特性 3 性能优势 4 平台兼容性 5 应用场景 6 特点 7 Windows编译 8 编译静态库及其测试示例下载 1 项目简介 Mbed TLS是一个由ARM Maintained的开源项目,它提供了一个轻量级的加密库,适用于嵌入式系统和物联网设备。这个项…

GESP C++等级考试 二级真题(2024年9月)

若需要在线模拟考试,可进入题库中心,在线备考,检验掌握程度: https://www.hixinao.com/tidan/exam-157.html?time1732669362&sid172&index1

upload-labs 靶场(11~21)

免责声明 本博客文章仅供教育和研究目的使用。本文中提到的所有信息和技术均基于公开来源和合法获取的知识。本文不鼓励或支持任何非法活动,包括但不限于未经授权访问计算机系统、网络或数据。 作者对于读者使用本文中的信息所导致的任何直接或间接后果不承担任何…

嵌入式硬件实战基础篇(四)多路直流稳压电源

设计一个多路直流稳压电源 要求设计制作一个多路输出直流稳压电源,可将220 V / 5 0HZ交流电转换为5路直流稳压输出。具体要求: 输出直流电压 12V, 5V;和一路输出3- 15V连续可调直流稳压电源: 输出电流Iom500mA; 稳压系数 Sr≤0.05;

【人工智能】深入解析GPT、BERT与Transformer模型|从原理到应用的完整教程

在当今人工智能迅猛发展的时代,自然语言处理(NLP)领域涌现出许多强大的模型,其中GPT、BERT与Transformer无疑是最受关注的三大巨头。这些模型不仅在学术界引起了广泛讨论,也在工业界得到了广泛应用。那么,G…

【计算机视觉+MATLAB】自动检测并可视化圆形目标:通过 imfindcircles 和 viscircles 函数

引言 自动检测图像中的圆形或圆形对象,并可视化检测到的圆形。 函数详解 imfindcircles imfindcircles是MATLAB中的一个函数,用于在图像中检测并找出圆形区域。 基本语法: [centers, radii] imfindcircles(A, radiusRange) [centers, r…

17. C++模板(template)1(泛型编程,函数模板,类模板)

⭐本篇重点:泛型编程,函数模板,类模板 ⭐本篇代码:c学习/07.函数模板 橘子真甜/c-learning-of-yzc - 码云 - 开源中国 (gitee.com) 目录 一. 泛型编程 二. 函数模板 2.1 函数模板的格式 2.2 函数模板的简单使用 2.3 函数模板…

学习threejs,设置envMap环境贴图创建反光效果

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.CubeTextureLoader 立…

v-for产生 You may have an infinite update loop in a component render function

参考文章&#xff1a; 报错解析 [Vue warn]: You may have an infinite update loop in a component render function. 另外一个解决方法 例如: MyList 是一个数组&#xff0c;我希望将排序后的结果返回进行for循环&#xff0c;因此设计了一个myMethon函数 <div v-for"…

spring boot框架漏洞复现

spring - java开源框架有五种 Spring MVC、SpringBoot、SpringFramework、SpringSecurity、SpringCloud spring boot版本 版本1: 直接就在根下 / 版本2:根下的必须目录 /actuator/ 端口:9093 spring boot搭建 1:直接下载源码打包 2:运行编译好的jar包:actuator-testb…

【Linux】线程的互斥和同步

【Linux】线程的互斥和同步 线程间的互斥 临界资源&#xff1a;多线程执行共享的资源就叫做临界资源临界区&#xff1a;每个线程内部&#xff0c;访问临界资源的代码&#xff0c;就叫做临界区互斥&#xff1a;任何时刻&#xff0c;互斥保证有且只有一个执行流进入临界区&#…