Advanced Macro Techniques in C/C++: `#`, `##`, and Variadic Macros
Advanced Macro Techniques in C/C++: #, ##, and Variadic Macros
文章目录
- Advanced Macro Techniques in C/C++: `#`, `##`, and Variadic Macros
- Illustrative Examples of Macros Using `#` and `##`
- Stringification Example
- Token Concatenation Example
- Nested Macros Example
- Key Concepts of Nested Macros
- Macro Expansion Rules
- Operators in Macro Definitions
- Challenges with `#` and `##`
- Detailed Example
- Example of Nested Macro Expansion
- Direct Expansion Example
- Why Use Nested Macros?
- Variable Argument Macros (Variadic Macros)
- Explanation
- Summary
| Date | Author | Version | Note |
|---|---|---|---|
| 2024-12-02 | Tao | V1.0 | Finish the document. |
Macros are an integral component of the C/C++ preprocessor, enabling the definition of reusable code fragments that enhance flexibility and abstraction. The # and ## operators are powerful tools used within macros for stringification and token concatenation, respectively. A deep understanding of these operators, particularly in nested contexts, allows for more sophisticated and reliable macro behavior.
The use of nested macros is a common technique in C and C++ to perform operations like token stringification or concatenation effectively through preprocessor directives. Mastering the behavior of macros when utilizing # (stringification) or ## (token concatenation) operators ensures that arguments are appropriately expanded, even when these arguments themselves involve other macro definitions.
Illustrative Examples of Macros Using # and ##
Stringification Example
#define Stringify(A) #A
printf("%s\n", Stringify(Hello)); // Output: "Hello"
Here, the # operator is used to convert the argument Hello into a string literal.
Token Concatenation Example
#define Concat(A, B) A##B
int HelloWorld = 5;
printf("%d\n", Concat(Hello, World)); // Output: 5
The ## operator concatenates Hello and World into a single token, HelloWorld.
Nested Macros Example
#define Outer(A) Inner(A)
#define Inner(A) #A
printf("%s\n", Outer(Hello)); // Output: "Hello"
By using nested macros, the argument is fully expanded before the stringification operation is applied.
Key Concepts of Nested Macros
Macro Expansion Rules
- Macros in C are expanded in a single pass unless explicitly nested within other macros.
- If a macro’s argument includes another macro, the preprocessor does not expand the inner macro unless explicitly instructed through an additional macro layer.
Operators in Macro Definitions
#: Converts a macro argument into a string literal.##: Concatenates two tokens into one.
Challenges with # and ##
When using # or ## within a macro, the preprocessor suppresses the evaluation of macro arguments before applying the operator. This suppression ensures that # or ## acts on the exact tokens provided, requiring an additional layer of macro indirection to achieve the desired behavior.
Detailed Example
Consider the following macro definitions:
#define Stringify(A) _Stringify(A) // Outer macro
#define _Stringify(A) #A // Inner macro that performs stringification#define Concat(A, B) _Concat(A, B) // Outer macro
#define _Concat(A, B) A##B // Inner macro that performs concatenation
-
Stringify Macro:
Stringify(A)passes its argumentAto_Stringify(A)._Stringify(A)then applies the#operator to convertAinto a string literal.
-
Concat Macro:
Concat(A, B)passes its argumentsAandBto_Concat(A, B)._Concat(A, B)uses the##operator to concatenateAandB.
Example of Nested Macro Expansion
Consider the following code:
printf("%s\n", Stringify(Concat(Hel, lo)));
-
Step 1: Expand
Stringify(Concat(Hel, lo)):Stringify(A)becomes_Stringify(A), whereAisConcat(Hel, lo).- Result:
_Stringify(Concat(Hel, lo)).
-
Step 2: Expand
_Stringify(Concat(Hel, lo)):- Before applying the
#operator, the macro argumentConcat(Hel, lo)is expanded because it is passed through another macro layer. Concat(Hel, lo)expands to_Concat(Hel, lo)and subsequently toHello(using the##operator).- Result:
_Stringify(Hello).
- Before applying the
-
Step 3: Apply
_Stringify(Hello):- The
#operator convertsHellointo a string literal. - Result:
"Hello".
- The
Output:
Hello
Direct Expansion Example
Consider the following code:
printf("%s\n", _Stringify(Concat(Hel, lo)));
- Step 1: Expand
_Stringify(Concat(Hel, lo)):_Stringify(A)directly applies the#operator to the argumentConcat(Hel, lo)without expanding it.- Result:
"Concat(Hel, lo)".
Output:
Concat(Hel, lo)
Why Use Nested Macros?
Nested macros ensure proper argument expansion before applying the # or ## operators. Without this nesting:
- The
#operator would stringify the literal macro argument without expanding it. - The
##operator would concatenate the original tokens rather than their expanded forms.
Variable Argument Macros (Variadic Macros)
Variadic macros allow for defining macros that accept a variable number of arguments. This feature is particularly advantageous for flexible logging or debugging macros.
Consider the following example:
#define Log(format, ...) printf(format, ##__VA_ARGS__)
Explanation
Log(format, ...)defines a macro that accepts a format string and a variable number of additional arguments.__VA_ARGS__is a special placeholder for the variable arguments.##__VA_ARGS__is used to handle the case where no additional arguments are provided, preventing a trailing comma error.
Usage Example:
Log("Error: %s, Code: %d\n", "File not found", 404); // Output: Error: File not found, Code: 404
Log("Simple message\n"); // Output: Simple message
Summary
- Utilize nested macros when dealing with macro arguments involving other macros and the
#or##operators. - The outer macro ensures arguments are fully expanded before being processed by the inner macro.
- Variadic macros (
...and__VA_ARGS__) provide the ability to create macros that accommodate a variable number of arguments, enhancing code flexibility and readability.
These examples illustrate the critical importance of proper macro usage:
- With Nested Macros:
Stringify(Concat(Hel, lo))correctly expands to"Hello". - Without Nested Macros:
_Stringify(Concat(Hel, lo))results in"Concat(Hel, lo)"due to the lack of proper expansion. - Variadic Macros: Provide a powerful mechanism for managing functions like logging without manual adjustments for the number of arguments.
相关文章:
Advanced Macro Techniques in C/C++: `#`, `##`, and Variadic Macros
Advanced Macro Techniques in C/C: #, ##, and Variadic Macros 文章目录 Advanced Macro Techniques in C/C: #, ##, and Variadic MacrosIllustrative Examples of Macros Using # and ##Stringification ExampleToken Concatenation ExampleNested Macros Example Key Conc…...
Maven、JAVAWeb、Servlet
知识点目标 1、MavenMaven是什么Maven项目的目录结构Maven的Pom文件Maven的命令Maven依赖管理Maven仓库JavaWeb项目 2.网络基础知识 3、ServletMaven Maven是什么 Maven是Java的项目管理工具,可以构建,打包,部署项目,还可以管理…...
分布式资源调度——yarn 概述(资源调度基本架构和高可用的实现)
此文章是学习笔记,图片均来源于B站:哈喽鹏程 yarn详细介绍 1、yarn 简介1.1 yarn的简介1.2 yarn 的基本架构1.3. yarn 的高可用 2、yarn 调度策略、运维、监控2.1 yarn 的调度策略2.1.1 FIFO scheduler(先进先出)2.1.2 容量调度2.1.3 公平调度 2.2 yarn…...
网页开发的http基础知识
请求方式-GET:请求参数在请求行中,没有请求体,如:/brand/findAll?nameoPPo&status1。GET请求大小在浏览器中是有限制的请求方式-POST:请求参数在请求体中,POST请求大小是没有限制的 HTTP请求…...
学习方法的进一步迭代————4
今天又在怀疑第二大脑的可靠程度 为什么呢? 还是因为自己没记住东西,感觉没学到东西。 其实自己知道大脑本就不应该用来存放知识而是用来思考知识,但是自己还是陷在里面了,我觉得其本质不是因为认知还不够,也不是因为还有点不适…...
数据科学家创建识别假图像的工具
Pixelator v2 是一款用于识别假图像的工具。它采用了全新的图像真实性技术组合,其能力超出了人眼所能看到的范围。 它能够以比传统方法更高的准确度识别图像中的细微差异,并且已被证明能够检测到小至 1 个像素的交替。 使用 SSIM 和 Pixelator v2 突出显…...
使用 GORM 与 MySQL 数据库进行交互来实现增删改查(CRUD)操作
1、安装 GORM 和 MySQL 驱动 新版本库是gorm.io/gorm go get -u gorm.io/gormgo get -u gorm.io/driver/mysql2、连接 MySQL 数据库 package mainimport ("gorm.io/driver/mysql""gorm.io/gorm""log" )func main() {// 数据源名称 (DSN) 格式&a…...
Day2 生信新手笔记: Linux基础
一、基础知识 1.1 服务器 super computer 或 server 1.2 组学数据分析 组学数据:如基因组学、转录组学、蛋白质组学等; 上游分析:主要涉及原始数据的获取和初步处理,计算量大,消耗的资源较多,在服务器完…...
001集—— 创建一个WPF项目 ——WPF应用程序入门 C#
本例为一个WPF应用(.NET FrameWork)。 首先创建一个项目 双击xaml文件 双击xaml文件进入如下界面,开始编写代码。 效果如下: 付代码: <Window x:Class"WpfDemoFW.MainWindow"xmlns"http://schema…...
【C++】1___引用
一、基本语法 数据类型 &别名 原名 #include<iostream> using namespace std; int main(){int a 10;int &b a;cout<<"a"<<a<<endl; // a10cout<<"b"<<b<<endl;// a10b 20;cout<<"a…...
如何通过 JWT 来解决登录认证问题
1. 问题引入 在登录功能的实现中 传统思路: 登录页面时把用户名和密码提交给服务器服务器验证用户名和密码,并把检验结果返回给后端如果密码正确,则在服务器端创建 session,通过 cookie 把 session id 返回给浏览器 但是正常情…...
高效集成:将聚水潭数据导入MySQL的实战案例
聚水潭数据集成到MySQL:店铺信息查询案例分享 在数据驱动的业务环境中,如何高效、准确地实现跨平台的数据集成是每个企业面临的重要挑战。本文将聚焦于一个具体的系统对接集成案例——将聚水潭的店铺信息查询结果集成到MySQL数据库中,以供BI…...
Jenkins-基于 JNLP协议的 Java Web 启动代理
在上一篇的基础配置上进行以下步骤 工作流程: 通过 JNLP 启动代理,客户端从 Jenkins 服务器上下载一个 agent.jar 文件。该文件启动时,代理程序通过 JNLP 协议连接到 Jenkins 主节点。一旦连接成功,代理节点就可以执行从主节点分…...
Qt数据库操作-QSqlQueryModel 的使用
QSqlQueryModel 功能概述 QSqlQueryModel 是 QSqlTableModel 的父类。QSqlQueryModel 封装了执行 SELECT 语句从数据库查询数据的功能,但是 QSqlQueryModel 只能作为只读数据源使用,不可以编辑数据。QSqlQueryModel 类的主要函数如下: 接口…...
C语言编程1.21波兰国旗问题
题目描述 桌上有 n ( 1 < n < 10000 ) 面小旗,一部分是白旗,一部分是红旗(波兰国旗由白色和红色组成)。唯一允许的操作是交换两面小旗位置。请你设计一个算法,用最少的交换操作将所有的白旗都置于红旗的之前。 输入格式 第一行为一个…...
如何利用微型5G网关为智慧无人矿车提供精确定位
随着5G、AI、物联网技术的发展和普及,越来越多行业正在加快生产、运营、管理的无人化、数字化与智能化,以适应当前我国“智慧、绿色、低碳”的新型发展模式需要。其中矿产业就是典型场景之一。针对矿山场景的智慧化、无人化转型,佰马提供基于…...
使用docker-compese部署SFTPGo详解
官网:SFTP & FTP as a Managed Service (SaaS) and On-premise 一、SFTPGo简介 SFTPGo 是一款功能强大的文件传输服务器软件。它支持多种协议(SFTP、SCP、FTP/S、WebDAV、HTTP/S)和多个存储后端。 借助 SFTPGo,您可以利用本地…...
Ajax基础总结(思维导图+二维表)
一些话 刚开始学习Ajax的时候,感觉很模糊,但是好像学什么都是这样的,很正常,但是当你学习的时候要持续性敲代码,边敲代码其实就可以理解很多了。然后在最后的总结,其实做二维表之后,就可以区分…...
Spring Task和WebSocket使用
在现代 Web 应用中,WebSocket 作为一种全双工通信协议,为实时数据传输提供了强大的支持。若要确保 WebSocket 在生产环境中的稳定性和性能,使用 Nginx 作为反向代理服务器是一个明智的选择。本篇文章将带你了解如何在 Nginx 中配置 WebSocket…...
微信小程序 本地调试和vconsole可以 但在体验上页面不请求数据
微信小程序页面不请求数据 本地调试和vconsole可以 但在体验版页面不请求数据,如遇到这类问题基本都是一样的解决办法 1、如何调试找到问题 首先要把小程序本地设置的不校验合法域名关掉,不然本地一直都是好的 然后通过本地真机调试打断点找到问题位…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...
什么是VR全景技术
VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...
渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...
