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

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;
}

相关文章:

  • 关于flutter中Scaffold.of(context).openEndDrawer();不生效问题
  • 【Golang笔记03】error、panic、fatal错误处理学习笔记
  • Go语言中内存释放 ≠ 资源释放
  • Java详解LeetCode 热题 100(20):LeetCode 48. 旋转图像(Rotate Image)详解
  • Linux入门(九)任务调度
  • 【Go】1、Go语言基础
  • 【Java高阶面经:消息队列篇】23、Kafka延迟消息:实现高并发场景下的延迟任务处理
  • 今日行情明日机会——20250523
  • Selenium 测试框架 - Java
  • el-input宽度自适应方法总结
  • 深入解析Spring Boot与Redis集成:高性能缓存实践
  • [crxjs]自己创建一个浏览器插件
  • Android中Binder驱动作用?
  • 【AS32X601驱动系列教程】GPIO_点亮LED详解
  • 服务器修改/home的挂载路径
  • HTB-Season8-Puppy-WriteUp
  • Teensy LC 一款由 PJRC 公司开发的高性能 32 位微控制器开发板
  • 图解深度学习 - 机器学习简史
  • 【Mini-F5265-OB开发板试用测评】2、关于platform.c中的串口号初始化修改的建议
  • vue中v-clock指令
  • 申请个网站要多少钱/青岛网络科技公司排名
  • 网站建设与管理怎么做/网站模板大全
  • 织梦做的网站首页打不开/广州seo
  • 用html制作网站流程/本网站三天换一次域名
  • 网站开发背景绪论/搜索推广营销
  • 官方网站建设需要做哪些东西/利于seo的建站系统有哪些