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

C++可变参数宏定义语法笔记

1. 基础语法

定义格式:

#define MACRO_NAME(fixed_args, ...) macro_body#define LOG(fmt, ...) printf(fmt, __VA_ARGS__)
LOG("Value: %d, Name: %s", 42, "Alice"); // 展开为 printf("Value: %d, Name: %s", 42, "Alice")

1)… 表示可变参数列表。
2)在宏体中,用 VA_ARGS 展开所有可变参数。

2. 处理空的可变参数

当可变参数为空时,直接使用 __VA_ARGS__ 可能导致语法错误(如尾随逗号)。可通过 ## 运算符优化:

使用 ##__VA_ARGS__

#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
LOG("Hello"); // 展开为 printf("Hello")(无尾随逗号)

## 在可变参数为空时,自动删除前面的逗号。

3. C++20 的 VA_OPT(可选展开)

C++20 引入 __VA_OPT__,可更灵活地控制可变参数的展开:

#define LOG(...) printf("Message: " __VA_ARGS__ __VA_OPT__(,) "\n")

当可变参数非空时,__VA_OPT__(,) 展开为 ,;为空时则不展开。

LOG("Error: %d", 404); // 展开为 printf("Message: " "Error: %d", 404 "\n")
LOG();                 // 展开为 printf("Message: " "\n")

4. 示例

(1) 调试日志

#define DEBUG(...) fprintf(stderr, "[DEBUG] " __VA_ARGS__)
DEBUG("File: %s, Line: %d\n", __FILE__, __LINE__);

(2) 泛型包装

#define CALL_FUNC(func, ...) func(__VA_ARGS__)
CALL_FUNC(printf, "Answer: %d", 42); // 展开为 printf("Answer: %d", 42)

(3) 条件编译

#ifdef VERBOSE#define LOG(...) printf(__VA_ARGS__)
#else#define LOG(...) (void)0
#endif

5. 注意事项

  1. 参数中的逗号:
    若参数包含未保护的逗号(如模板类型),需用括号包裹:
LOG("Types: %s", (std::vector<int>, std::map<std::string, float>));
  1. 兼容性:
    ##__VA_ARGS__是 GNU 扩展,但主流编译器(GCC、Clang、MSVC)均支持。
    __VA_OPT__ 是 C++20 标准特性,需编译器支持。

  2. 避免副作用:
    宏展开可能导致多次参数求值:

#define SQUARE_SUM(x, ...) ((x)*(x) + SQUARE_SUM(__VA_ARGS__))
// 错误:递归展开可能导致无限循环
#include <cstdio>// 可变参数宏:支持格式化字符串和可变参数
#define LOG(fmt, ...) printf("[INFO] " fmt "\n", ##__VA_ARGS__)int main() {LOG("Start");              // 输出: [INFO] StartLOG("Sum: %d", 3 + 5);     // 输出: [INFO] Sum: 8return 0;
}
http://www.lryc.cn/news/2385009.html

相关文章:

  • 基于BERT预训练模型(bert_base_chinese)训练中文文本分类任务(AI老师协助编程)
  • Windows逆向工程提升之IMAGE_EXPORT_DIRECTORY
  • python与flask框架
  • 【普及+/提高】洛谷P2613 【模板】有理数取余——快读+快速幂
  • 从数据到智能:openGauss+openEuler Intelligence的RAG架构实战
  • 【Linux】初见,基础指令
  • 什么是实时流数据?核心概念与应用场景解析
  • 工业RTOS生态重构:从PLC到“端 - 边 - 云”协同调度
  • 数据结构与算法学习笔记(Acwing 提高课)----动态规划·状态机模型
  • 基于开源链动2+1模式AI智能名片S2B2C商城小程序的社群构建与新型消费迎合策略研究
  • 高性能RPC框架--Dubbo(五)
  • 计算机视觉与深度学习 | PSO-MVMD粒子群算法优化多元变分模态分解(Matlab完整代码和数据)
  • 搭建自己的语音对话系统:开源 S2S 流水线深度解析与实战
  • feign调用指定服务ip端口
  • 【深尚想!爱普特APT32F1023H8S6单片机重构智能电机控制新标杆】
  • vue2 中的过滤器以及vue3中的替换方案
  • Unity EventCenter 消息中心的设计与实现
  • 瑞萨单片机笔记
  • 300. 最长递增子序列【 力扣(LeetCode) 】
  • MySQL远程连接10060错误:防火墙端口设置指南
  • 使用 OpenCV 实现 ArUco 码识别与坐标轴绘制
  • 2024CCPC辽宁省赛 个人补题 ABCEGJL
  • #6 百日计划第六天 java全栈学习
  • AOP的代理模式
  • 解决leetcode第3548题.等和矩阵分割II
  • 深入解析自然语言处理中的语言转换方法
  • redis 进行缓存实战-18
  • JFace中MVC的表的单元格编辑功能的实现
  • 在 Excel xll 自动注册操作 中使用东方仙盟软件2————仙盟创梦IDE
  • canal实现mysql数据同步