C/C++ #define与编译器的预处理

文章目录

  • 预处理
  • #define
  • 新版本特性
    • 旧版本特性
    • #define除了定义明示常量的其他用途
  • #define的组成
    • #define本身:预处理指令
    • 替换列表或替换体
      • 宏展开
  • 参考资料

预处理

在预处理之前,编译器必须对该程序进行一些翻译处理。首先,编译器
把源代码中出现的字符映射到源字符集。该过程处理多字节字符和三字符序
列——字符扩展让C更加国际化。

第二,编译器定位每个反斜杠后面跟着换行符的实例,并删除它们。也
就是说,把下面两个物理行(physical line):

printf("That's wond\
erful!\n");

转换成一个逻辑行(logical line):

printf("That's wonderful\n!");

注意,在这种场景中,“换行符”的意思是通过按下Enter键在源代码文件
中换行所生成的字符,而不是指符号表征\n。

由于预处理表达式的长度必须是一个逻辑行,所以这一步为预处理器做
好了准备工作。一个逻辑行可以是多个物理行。

第三,编译器把文本划分成预处理记号序列、空白序列和注释序列(记
号是由空格、制表符或换行符分隔的项)。
这里要注意的是,编译器将用一个空格字符替换每一条注释。因此,下面的代码:

int/* 这看起来并不像一个空格*/fox;

将变成:

int fox;

而且,实现可以用一个空格替换所有的空白字符序列(不包括换行符)。最后,程序已经准备好进入预处理阶段,预处理器查找一行中以#号开始的预处理指令。

#define

新版本特性

#define预处理器指令和其他预处理器指令一样,以#号作为一行的开
始。ANSI和后来的标准都允许#号前面有空格或制表符,而且还允许在#和
指令的其余部分之间有空格。

旧版本特性

但是旧版本的C要求指令从一行最左边开始,而且#和指令其余部分之间不能有空格。指令可以出现在源文件的任何地方,其定义从指令出现的地方到该文件末尾有效。

#define除了定义明示常量的其他用途

我们大量使用#define指令来定义明示常量(manifest constant)(也叫做符号常量),但是该指令还有许多其他用途。

以下程序演示了#define指令的一些用法和属性。
预处理器指令从#开始运行,到后面的第1个换行符为止。也就是说,指令的长度仅限于一行。然而,前面提到过,在预处理开始前,编译器会把多行物理行处理为一行逻辑行。

/* preproc.c -- 简单的预处理示例 */
#include <stdio.h>
#define TWO 2 /* 可以使用注释 */
#define OW "Consistency is the last refuge of the unimagina\
tive.- Oscar Wilde" /* 反斜杠把该定义延续到下一行 */
#define FOUR TWO*TWO
#define PX printf("X is %d.\n", x)
#define FMT "X is %d.\n"
int main(void)
{
	int x = TWO;
	PX;
	x = FOUR;
	printf(FMT, x);
	printf("%s\n", OW);
	printf("TWO: OW\n");
	return 0;
}

输出:

运行该程序示例后,输出如下:
X is 2.
X is 4.
Consistency is the last refuge of the unimaginative.- Oscar Wilde
TWO: OW
下面分析具体的过程。下面的语句:
int x = TWO;
变成了:
int x = 2;
2代替了TWO。而语句:
PX;
变成了:
printf("X is %d.\n", x);

这里同样进行了替换。这是一个新用法,到目前为止我们只是用宏来表
示明示常量。从该例中可以看出,宏可以表示任何字符串,甚至可以表示整
个 C 表达式。但是要注意,虽然 PX 是一个字符串常量,它只打印一个名为
x的变量。

下一行也是一个新用法。读者可能认为FOUR被替换成4,但是实际的
过程是:

x = FOUR;

变成了:

x = TWO*TWO;

即是:

x = 2*2;

宏展开到此处为止。由于编译器在编译期对所有的常量表达式(只包含
常量的表达式)求值,所以预处理器不会进行实际的乘法运算,这一过程在
编译时进行。预处理器不做计算,不对表达式求值,它只进行替换。

#define的组成

每行#define(逻辑行)都由3部分组成。

#define本身:预处理指令

第1部分是#define指令本身。

第2部分是选定的缩写,也称为宏。有些宏代表值(如本例),这些宏被称为
类对象宏(object-like macro)。C 语言还有类函数宏(function-like
macro),稍后讨论。宏的名称中不允许有空格,而且必须遵循C变量的命
名规则:只能使用字符、数字和下划线(_)字符,而且首字符不能是数
字。

替换列表或替换体

第3部分(指令行的其余部分)称为替换列表或替换体(见图)。
在这里插入图片描述

宏展开

一旦预处理器在程序中找到宏的示实例后,就会用替换体代替该宏(也有例外,稍后解释)。从宏变成最终替换文本的过程称为宏展开(macro expansion)。

注意,可以在#define行使用标准C注释。如前所述,每条注释都会被一个空格代替。

参考资料

《C Primer Plus》

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WampServer下载安装并结合内网穿透实现本地服务的公网访问

文章目录 前言1.WampServer下载安装2.WampServer启动3.安装cpolar内网穿透3.1 注册账号3.2 下载cpolar客户端3.3 登录cpolar web ui管理界面3.4 创建公网地址 4.固定公网地址访问 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的 人工智能学习网站&#xff0c;…

【Kettle实战】数据分批处理及参数化传递子作业任务

对于大表操作&#xff0c;本来离线数据需要分批处理&#xff0c;刚开始只会用具体日期去做&#xff0c;通过复制多分转换和作业来处理。当日期范围大了后&#xff0c;这是个苦力活儿&#xff0c;kettle里面有参数化传递功能&#xff0c;多动手实操&#xff0c;懂得灵活变通自然…

宝塔开心版hostcli的广告去除

首先感谢hostcli把宝塔7.6剥离了&#xff0c;直接安装我这里是缺少pyenv的包。 直接进入正题吧。 定位到页面左下方的广告位于 /www/server/panel/BTPanel/templates/default/layout.html “退出”按钮下方有条线开始去掉 去掉之前的忘了截图了&#xff0c;就这样吧&#xff…

力扣每日一道系列 --- LeetCode 160. 相交链表

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构探索 ✅LeetCode每日一道 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 文章目录 LeetCode 160. 相交链表 思路&#xff1a; 首先计算两个链表的长度&#xff0c;然后判…

日本it培训班,如何选择靠谱的赴日IT培训班?

随着科技的发展&#xff0c;信息技术行业在全球范围内迅速发展&#xff0c;并呈现出蓬勃的发展态势&#xff0c;在日本&#xff0c;IT行业也成为一种极为热门的职业选择。日本专门学校在这个领域内培养了许多IT从业者&#xff0c;成为了众多IT公司的培养基地。如果你对IT产业感…

【前端异常】JavaScript错误处理:分析 Uncaught(in promise) error

这里写目录标题 一、Promise是什么二、什么是 Uncaught(in promise) error三、解决方案3.1 使用catch方法处理Promise的错误3.2 使用 async/await 处理Promise的错误3.3 全局异常处理 四、结论 在开发过程中&#xff0c;JavaScript的错误处理是一个老生常谈的话题。当应用程序发…

高效筛选的秘密武器:JVS智能BI的‘and’与‘or’逻辑

在这个信息爆炸的时代&#xff0c;数据被誉为新时代的黄金和石油&#xff0c;蕴含着无尽的价值和潜力。然而&#xff0c;随着数据的爆炸式增长&#xff0c;如何高效、准确地从海量数据中提取出真正有价值的信息&#xff0c;成为摆在我们面前的一大挑战。我们需要用数据筛选工具…

虚拟仪器软件结构VISA

1、什么是VISA VISA是虚拟仪器软件结构(Virtual Instrument Software Architectuere)的简称&#xff0c;是由VXI plug & play系统联盟所统一制定的I/O接口软件标准及其相关规范的总称。一般称这个I/O函数库为VISA库&#xff08;用于仪器编程的标准I/O函数库&#xff09;。…

链动2+1模式系统开发之区域代理深度解析

区域代理的保护机制&#xff1a;在链动商城系统里设定的代理有唯一性&#xff0c;每个省只有一个省代&#xff0c;每个市只有一个市代&#xff0c;每个区县只有一个区县代。这样也是保护每个代理的收益权益。 区域代理包含的权益类别&#xff1a;购物奖励折扣&#xff1b;区域实…

OpenAI DALL·E 3文生图模型技术揭秘(建议收藏)

欢迎来到魔法宝库&#xff0c;传递AIGC的前沿知识&#xff0c;做有格调的分享❗ 喜欢的话记得点个关注吧&#xff01; DALLE 3是OpenAI发布的一款文生成图AI系统&#xff0c;它无缝接入ChatGPT&#xff0c;通过接受文本提示作为输入&#xff0c;生成相应的图像作为输出。先来看…

字典管理怎么使用,vue3项目使用若依的的字典管理模块

若依框架数据字典的使用_若依数据字典_哈哈水水水水的博客-CSDN博客 【精选】关于数据字典的理解与设计_数据字典怎么设计-CSDN博客 若依的字典值如何使用&#xff08;超详细图文教程&#xff09;_若依字典管理_丿BAIKAL巛的博客-CSDN博客 Vue3组合式API&#xff1a;getCurr…

基于ssm的高校失物招领管理系统

基于ssm的高校失物招领管理系统 摘要 失物招领管理系统是一种利用现代信息技术&#xff0c;为高校提供高效、便捷的失物招领服务的平台。本系统基于SSM框架&#xff08;Spring SpringMVC MyBatis&#xff09;&#xff0c;充分利用了各框架的优势&#xff0c;实现了系统的稳定…

Docker 和 Kubernetes:技术相同和不同之处

Docker和Kubernetes是当今最流行的容器化技术解决方案。本文将探讨Docker和Kubernetes的技术相似之处和不同之处&#xff0c;以帮助读者更好地理解这两种技术。 Docker和Kubernetes&#xff1a;当今最流行的容器化技术解决方案 在当今的IT领域&#xff0c;Docker和Kubernetes无…

Python实现WOA智能鲸鱼优化算法优化BP神经网络分类模型(BP神经网络分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 鲸鱼优化算法 (whale optimization algorithm,WOA)是 2016 年由澳大利亚格里菲斯大学的Mirjalili 等提…

解密.devos病毒:如何守护你的数据免受.devos病毒威胁?

引言&#xff1a; 近来&#xff0c;网络安全威胁再次升级&#xff0c;其中一个备受关注的恶意软件就是.devos病毒。这种病毒通过加密你的数据文件&#xff0c;然后勒索赎金&#xff0c;给用户带来了巨大的威胁。本文将介绍如何应对被.devos病毒加密的数据文件&#xff0c;以及…

HashSet源码分析

HashSet内部实现很简单&#xff0c;只要看明白HashMap&#xff0c;就可以了 类图结构&#xff1a; public class HashSet<E>extends AbstractSet<E>implements Set<E>, Cloneable, java.io.Serializable {static final long serialVersionUID -502474440…

Java图像编程之:Graphics2D

一、介绍 1、Java图像编程的核心类 BufferedImage&#xff1a;用于表示图像的类&#xff0c;可以进行像素级的操作。Image&#xff1a;表示图像的抽象类&#xff0c;是所有图像类的基类。ImageIcon&#xff1a;用于显示图像的类&#xff0c;可以将图像嵌入到Swing组件中。Ima…

全国不同级别高炉炼铁主要操作指标与分析

参考网址&#xff1a;https://www.zgltw.cn/liantiexinjishu/2020/0114/23584.html &#xff08;中国炼铁网&#xff09; 参考网址&#xff1a;https://www.zgltw.cn/liantiexinjishu/2020/0114/23584.html &#xff08;中国炼铁网 世界金属导报&#xff09;

RT-DETR算法优化改进:可变形大核注意力(D-LKA Attention),超越自注意力,实现暴力涨点 | 2023.8月最新发表

💡💡💡本文独家改进: 可变形大核注意力(D-LKA Attention),采用大卷积核来充分理解体积上下文的简化注意力机制,来灵活地扭曲采样网格,使模型能够适当地适应不同的数据模式 1)代替RepC3进行使用; 推荐指数:五星 RT-DETR魔术师专栏介绍: https://blog.csdn.n…

Transformer详解一:transformer的由来和先导知识

目录 参考资料前言一、预训练二、神经网络语言模型&#xff08;NNLM&#xff09;&#xff1a;预测下一个词one-hot编码的缺陷词向量&#xff08;word embedding&#xff09; 三、Word2Vec模型&#xff1a;得到词向量CBOWSkip-gramWord2Vec和NNLM的区别Word2Vec的缺陷 四、ELMO模…