C C++帶多個引數的巨集(...與__VA_ARGS__詳解)
阿新 • • 發佈:2019-02-20
C C++帶多個引數的巨集(...
與__VA_ARGS__
詳解)
1. 環境
- gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
2.'...'與__VA_ARGS__
這裡的...
代表多個引數,在巨集展開時,編譯器會經...
的引數替換__VA_ARGS__
例1:main.c檔案敲入如下程式碼
#define debug(format, ...) printf (format, __VA_ARGS__)
#include <stdio.h>
void main(){
debug("Hello %s\n" , "world");
}
使用預編譯命令gcc -E main.c -o main.i
看看展開後是什麼效果:
void main(){
printf ("Hello %s\n", "world");
}
3. 多引數別名
__VA_ARGS__
這個名字似乎很難寫,gcc支援另一種更加人性化的寫法:
例2:
#define debug(format, args...) printf (format, args)
#include <stdio.h>
void main(){
debug("Hello %s\n", "world");
}
展開後效果跟第一種寫法是一樣的:
void main(){
printf ("Hello %s\n", "world");
}
4. 空引數與##
前面兩個例子都傳入了兩個引數,如果...
沒有傳進引數會發生什麼事情呢:
#define debug(format, ...) printf (format, __VA_ARGS__)
#include <stdio.h>
void main(){
debug("Hello world\n");
}
展開後:
void main(){
printf ("Hello world\n", );
}
可以看到Hello world後面帶來一個,
這個時候就會導致編譯出錯。##
的出現就是為了解決這個問題:
當...
沒有傳進引數時,預編譯器會將最後面的,
刪除
#define debug(format, ...) printf (format, ##__VA_ARGS__)
#include <stdio.h>
void main(){
debug("Hello world\n");
}
展開後效果:
void main(){
printf ("Hello world\n");
}
5. 稍微複雜的例子
專案中也會加上呼叫的行號,方法名稱以方便debug:
#define __log(...) \
do \
{ \
printf(__VA_ARGS__); \
} while(0)
#define __format(__fmt__) "%d " __fmt__ "\n"
#define log(__fmt__, ...) \
do \
{ \
__log(__format(__fmt__), __LINE__,##__VA_ARGS__); \
}while(0)
#include <stdio.h>
void main(){
log("Hello %s", "world");
}
6. 總結
一定要看官方文件,看官方文件,看官方文件。重要的事情說三遍,儘早養成看官方文件的習慣。