在系統在整合或移值時最常用的就是以巨集來置換一些底層 function. 這類的技巧叫 wrapper (意思是包裝紙)
但是在面對像 printf() 或者 scanf() 之類參數個數可變 (或稱不具名參數) 的函數, 就出現只能更換函數名稱, 而無法增減參數個數的冏境, 例如:
// 下例 OK, 但是無法處理參數的異動
#define printf my_printf
// 下例 OK, 但是只能處理剛好二個參數的異動 (增加, 交換)
#define printf(a, b) my_printf(x, b, a)
// 下例 ERR, C 編譯器的 preprocessor 不認識 ...
#define printf(a, b, ...) my_printf(x, a, b, ...)
下面這二種用法在 GNU GCC 或者符合 C99 標準的 C 編譯器 preprocessor 有支援.
// C99 Standard
#define printf(fmt, ...) my_printf(fmt, __VA_ARGS__)
// GCC old style
#define printf(a, b, args...) my_printf(x, b, a, args)
這個問題, 如果限定只能使用 #define, 而且 C 編譯器的 preprocessor 又不支援的話目前所知是無解的.
看過有人使用第二組括號來將變動參數括住, 好讓 preprocessor 把它當成一個參數而已, 但限制是程式一開始就要換一個寫法, 所以只能處理自己寫的程式, 想要快速移植別人的程式就不管用了.
#define DEGUG(FORMAT,ARGS) printf(FORMAT, ARGS)
DEBUG("%s = %f\n", ("x",0) );
// 上一行替換後相當於這樣
printf("%s = %f\n", "x", 0 );
下面的例子也是利用兩組括號的技巧
#if (DEBUG)
#define DBGMSG(x) { printf x; }
#else
#define DBGMSG(x)
#endif
DBGMSG(("msg format %d, %X", a, b));
// DEBUG 為假時, 上一行會替換空白行
// DEBUG 為真時, 會替換後相當於這樣
printf("msg format %d, %X", a, b);
如果不限定只用 #define, 則我們可以使用 stdarg.h 來處理變動的參數. 請參考這篇
文章標籤
全站熱搜
留言列表