当前位置: 首页 > news >正文

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

DateAuthorVersionNote
2024-12-02TaoV1.0Finish 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 argument A to _Stringify(A).
    • _Stringify(A) then applies the # operator to convert A into a string literal.
  • Concat Macro:

    • Concat(A, B) passes its arguments A and B to _Concat(A, B).
    • _Concat(A, B) uses the ## operator to concatenate A and B.

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), where A is Concat(Hel, lo).
    • Result: _Stringify(Concat(Hel, lo)).
  • Step 2: Expand _Stringify(Concat(Hel, lo)):

    • Before applying the # operator, the macro argument Concat(Hel, lo) is expanded because it is passed through another macro layer.
    • Concat(Hel, lo) expands to _Concat(Hel, lo) and subsequently to Hello (using the ## operator).
    • Result: _Stringify(Hello).
  • Step 3: Apply _Stringify(Hello):

    • The # operator converts Hello into a string literal.
    • Result: "Hello".

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 argument Concat(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:

  1. With Nested Macros: Stringify(Concat(Hel, lo)) correctly expands to "Hello".
  2. Without Nested Macros: _Stringify(Concat(Hel, lo)) results in "Concat(Hel, lo)" due to the lack of proper expansion.
  3. 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请求&#xf…...

学习方法的进一步迭代————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应用&#xff08;.NET FrameWork&#xff09;。 首先创建一个项目 双击xaml文件 双击xaml文件进入如下界面&#xff0c;开始编写代码。 效果如下&#xff1a; 付代码&#xff1a; <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. 问题引入 在登录功能的实现中 传统思路&#xff1a; 登录页面时把用户名和密码提交给服务器服务器验证用户名和密码&#xff0c;并把检验结果返回给后端如果密码正确&#xff0c;则在服务器端创建 session&#xff0c;通过 cookie 把 session id 返回给浏览器 但是正常情…...

高效集成:将聚水潭数据导入MySQL的实战案例

聚水潭数据集成到MySQL&#xff1a;店铺信息查询案例分享 在数据驱动的业务环境中&#xff0c;如何高效、准确地实现跨平台的数据集成是每个企业面临的重要挑战。本文将聚焦于一个具体的系统对接集成案例——将聚水潭的店铺信息查询结果集成到MySQL数据库中&#xff0c;以供BI…...

Jenkins-基于 JNLP协议的 Java Web 启动代理

在上一篇的基础配置上进行以下步骤 工作流程&#xff1a; 通过 JNLP 启动代理&#xff0c;客户端从 Jenkins 服务器上下载一个 agent.jar 文件。该文件启动时&#xff0c;代理程序通过 JNLP 协议连接到 Jenkins 主节点。一旦连接成功&#xff0c;代理节点就可以执行从主节点分…...

Qt数据库操作-QSqlQueryModel 的使用

QSqlQueryModel 功能概述 QSqlQueryModel 是 QSqlTableModel 的父类。QSqlQueryModel 封装了执行 SELECT 语句从数据库查询数据的功能&#xff0c;但是 QSqlQueryModel 只能作为只读数据源使用&#xff0c;不可以编辑数据。QSqlQueryModel 类的主要函数如下&#xff1a; 接口…...

C语言编程1.21波兰国旗问题

题目描述 桌上有 n ( 1 < n < 10000 ) 面小旗&#xff0c;一部分是白旗&#xff0c;一部分是红旗(波兰国旗由白色和红色组成)。唯一允许的操作是交换两面小旗位置。请你设计一个算法&#xff0c;用最少的交换操作将所有的白旗都置于红旗的之前。 输入格式 第一行为一个…...

如何利用微型5G网关为智慧无人矿车提供精确定位

随着5G、AI、物联网技术的发展和普及&#xff0c;越来越多行业正在加快生产、运营、管理的无人化、数字化与智能化&#xff0c;以适应当前我国“智慧、绿色、低碳”的新型发展模式需要。其中矿产业就是典型场景之一。针对矿山场景的智慧化、无人化转型&#xff0c;佰马提供基于…...

使用docker-compese部署SFTPGo详解

官网&#xff1a;SFTP & FTP as a Managed Service (SaaS) and On-premise 一、SFTPGo简介 SFTPGo 是一款功能强大的文件传输服务器软件。它支持多种协议&#xff08;SFTP、SCP、FTP/S、WebDAV、HTTP/S&#xff09;和多个存储后端。 借助 SFTPGo&#xff0c;您可以利用本地…...

Ajax基础总结(思维导图+二维表)

一些话 刚开始学习Ajax的时候&#xff0c;感觉很模糊&#xff0c;但是好像学什么都是这样的&#xff0c;很正常&#xff0c;但是当你学习的时候要持续性敲代码&#xff0c;边敲代码其实就可以理解很多了。然后在最后的总结&#xff0c;其实做二维表之后&#xff0c;就可以区分…...

Spring Task和WebSocket使用

在现代 Web 应用中&#xff0c;WebSocket 作为一种全双工通信协议&#xff0c;为实时数据传输提供了强大的支持。若要确保 WebSocket 在生产环境中的稳定性和性能&#xff0c;使用 Nginx 作为反向代理服务器是一个明智的选择。本篇文章将带你了解如何在 Nginx 中配置 WebSocket…...

微信小程序 本地调试和vconsole可以 但在体验上页面不请求数据

微信小程序页面不请求数据 本地调试和vconsole可以 但在体验版页面不请求数据&#xff0c;如遇到这类问题基本都是一样的解决办法 1、如何调试找到问题 首先要把小程序本地设置的不校验合法域名关掉&#xff0c;不然本地一直都是好的 然后通过本地真机调试打断点找到问题位…...

.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>…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

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 打不开&#xff0c;快捷键也不好用&#xff0c;当看到 Cursor 升级后&#xff0c;还是蛮高兴的 1. 下载 Cursor 下载地址&#xff1a;https://www.cursor.com/cn/downloads 点击下载 Linux (x64) &#xff0c;…...

什么是VR全景技术

VR全景技术&#xff0c;全称为虚拟现实全景技术&#xff0c;是通过计算机图像模拟生成三维空间中的虚拟世界&#xff0c;使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验&#xff0c;结合图文、3D、音视频等多媒体元素…...

深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向

在人工智能技术呈指数级发展的当下&#xff0c;大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性&#xff0c;吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型&#xff0c;成为释放其巨大潜力的关键所在&…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...