調試打印、日誌記錄等場景常需可變參數宏。C99 標準化 __VA_ARGS__,GCC 提供擴展語法,兩者細節不同,需注意兼容性與陷阱。
__VA_ARGS__#define debug(format, ...) fprintf(stderr, format, __VA_ARGS__)
debug("msg: %d\n", 123); → 正常展開。debug("msg"); → 展開為 fprintf(stderr, "msg", ); 多出逗號,**編譯錯誤**。-std=c99 或 GNU 擴展)。args...#define debug(format, args...) fprintf(stderr, format, args)
args 如同普通參數。##__VA_ARGS__(推薦)#define debug(format, ...) fprintf(stderr, format, ##__VA_ARGS__)
__VA_ARGS__ 為空,## 會刪除前面的逗號;若非空,正常展開參數。debug("msg"); → fprintf(stderr, "msg"); **編譯通過**。#define DEBUG(args) (printf("DEBUG: "), printf(args))
DEBUG(("value: %d\n", 42)); —— 雙層括號模擬參數列表。##__VA_ARGS__ 寫法,兼容 C99/GCC/MSVC。do { ... } while(0) 包裹多語句宏,避免控制流陷阱。std::ostream 或 fmt 庫等類型安全方案替代宏。#define LOG(level, fmt, ...) \
do { \
if (level <= g_log_level) { \
fprintf(stderr, "[%s] " fmt "\n", level_str(level), ##__VA_ARGS__); \
} \
} while(0)