1. #用來標記參數是字符串
#define STRING(X) #X
const char *str = STRING(test);
cout << str << endl;
這裏str的內容就是"test"
2. ##用來連接參數
#define AND(X) X##X
int num = AND(8);
cout << num << endl;
這裏num的內容就是88
3. __VA_ARGS__可變參數宏
#define PRINTF_ERROR(format, ...) \
printf("[%s %s] [ERROR] %s:%d %s() " format" errno:%d err:%s\n", \
__DATE__, __TIME__, __FILE__, __LINE__, __FUNCTION__, \
##__VA_ARGS__, errno, strerror(errno))
PRINTF_ERROR("test::print %s %s", str1, str2);
format照寫,__VA_ARGS__是系統預定義宏,代表了...這個可變參數列表。
其實在gcc中還支持可變參數名
#define PRINTF_ERROR(format, args...) \
printf("[%s %s] [ERROR] %s:%d %s() " format" errno:%d err:%s\n", \
__DATE__, __TIME__, __FILE__, __LINE__, __FUNCTION__, \
##args, errno, strerror(errno))
PRINTF_ERROR("test::print %s %s", str1, str2);
這樣可以用args代替可變參數列表...
這裏__VA_ARGS__和args前面都帶上了##,是因爲如果你使用PRINTF_ERROR,卻沒有可變參數,例如
PRINTF_ERROR("server start success");
就會編譯報錯。爲了兼容有可變參數和沒有可變參數的情況,加上了##
細心的會發現format和前面的引號之間有空格,這是因爲C++11告警invalid suffix on literal; C++11 requires a space between literal and identifier [-Wliteral-suffix]