#ifdef _DEBUG ... #endif 包裹每處呼叫,冗長。#define DEBUG_PRINT DebugPrint / #define DEBUG_PRINT (空)。DEBUG_PRINT("Hello, %s", "World") 參數仍求值,可能有副作用 (如函式呼叫)。#define DEBUG_PRINT /*/ DebugPrint 變註解。void DebugPrint(const char *format, ...); // 實際輸出函式
#ifdef _DEBUG
#define DEBUG_PRINT(fmt, ...) DebugPrint(fmt, __VA_ARGS__)
#else
#define DEBUG_PRINT(fmt, ...) ((void)0) // 空運算,參數不求值
#endif
(void)0,參數表達式完全不計算。DEBUG_PRINT(...); 為完整語句,不影響後續代碼。DebugPrint,保留 printf 風格格式化能力。| 編譯器 | 支援 | 備註 |
|---|---|---|
| GCC / Clang | ✅ 完美 | 支援 ##__VA_ARGS__ 擴展 |
| MSVC 2013+ (VS2013+) | ✅ 支援 | 標準 __VA_ARGS__ |
| MSVC 2008/2010 | ⚠️ 部分 | 需測試,可能需 __VA_ARGS__ 無擴展 |
| VC6.0 | ❌ 不支援 | C99 標準發布時 VC6 已停維護 |
// 僅除錯版輸出詳細資訊
#ifdef _DEBUG
#define LOG_DEBUG(fmt, ...) DebugPrint("[DBG]" fmt, __VA_ARGS__)
#else
#define LOG_DEBUG(fmt, ...) ((void)0)
#endif
// 釋出版也輸出關鍵錯誤/警告
#define LOG_ERROR(fmt, ...) DebugPrint("[ERR]" fmt, __VA_ARGS__)
#define LOG_WARN(fmt, ...) DebugPrint("[WRN]" fmt, __VA_ARGS__)
#include <stdio.h>
#include <stdarg.h>
void DebugPrint(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
#ifdef _DEBUG
#define DEBUG_PRINT(fmt, ...) DebugPrint(fmt, __VA_ARGS__)
#else
#define DEBUG_PRINT(fmt, ...) ((void)0)
#endif
int main() {
int a = 10, b = 20;
DEBUG_PRINT("a=%d, b=%d, sum=%d\n", a, b, a+b); // _DEBUG 時輸出
return 0;
}
C99 __VA_ARGS__ 讓巨集擁有函式級的參數處理能力。結合 #ifdef 與空運算 (void)0,即可打造除錯版完整功能、釋出版零開銷零副作用的專業級日誌巨集。若專案仍在 VC6,請升級編譯器或退回函式指標方案;現代 C/C++ 專案,此為標準最佳實踐。