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、如何调试找到问题 首先要把小程序本地设置的不校验合法域名关掉,不然本地一直都是好的 然后通过本地真机调试打断点找到问题位…...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
离线语音识别方案分析
随着人工智能技术的不断发展,语音识别技术也得到了广泛的应用,从智能家居到车载系统,语音识别正在改变我们与设备的交互方式。尤其是离线语音识别,由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力,广…...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...
