1. 程式人生 > >巨集定義中的特殊引數(#、##、...和__VA_ARGS__) 【轉】

巨集定義中的特殊引數(#、##、...和__VA_ARGS__) 【轉】

轉自:http://blog.csdn.net/cqupt_chen/article/details/8055215

最近在android的某個程式碼的標頭檔案中發現很多__VA_ARGS__,google一下.還是比較有用.附帶其它巨集定義引數,一起記錄之.

1.    ...和__VA_ARGS__

看看msdn上給得例子吧

[cpp] view plaincopyprint?
  1. #include <stdio.h>
  2. #define EMPTY
  3. #define CHECK1(x, ...) if (!(x)) { printf(__VA_ARGS__); }
  4. #define CHECK2(x, ...) if ((x)) { printf(__VA_ARGS__); }
  5. #define CHECK3(...) { printf(__VA_ARGS__); }
  6. #define MACRO(s, ...) printf(s, __VA_ARGS__)
  7. int main() {  
  8.     CHECK1(0, "here %s %s %s""are""some""varargs1(1)\n");  
  9.     CHECK1(1, "here %s %s %s""are""some""varargs1(2)\n");   // won't print
  10.     CHECK2(0, "here %s %s %s""are""some""varargs2(3)\n"
    );   // won't print
  11.     CHECK2(1, "here %s %s %s""are""some""varargs2(4)\n");  
  12.     // always invokes printf in the macro
  13.     CHECK3("here %s %s %s""are""some""varargs3(5)\n");  
  14.     MACRO("hello, world\n");  
  15.     // MACRO("error\n", EMPTY);   would cause C2059
  16. }  

我們看看輸出:

here are some varargs1(1)
here are some varargs2(4)


here are some varargs3(5)
hello, world

是不是很有趣,以後我們如果在一些情況下要定義自己的列印函式就特別方便了

比如我們要在A條件成立,且B條件不成立的情況下列印輸出

可以做如下定義:

[cpp] view plaincopyprint?
  1. #define CHECK1(A,B,...) if ((A)&&!(B)) { printf(__VA_ARGS__); }

記住一點...只能代替後面的引數,如下定義可行不通: [cpp] view plaincopyprint?
  1. #define W(x,...,y)

是不是很像C++的函式的預設引數一樣.

2.   #

這個特殊的巨集定義引數也特別有用.#作為一個預處理運算子,它可以把語言符號字串化(stringizing).例如我們定義的變數等.

看一個簡單的例子:

[cpp] view plaincopyprint?
  1. #include <stdio.h>
  2. #define TEST(x) printf("square of  " #x " is %d.\n",(x)*(x))
  3. void main()  
  4. {  
  5.     int y =4;  
  6.     TEST(y);  
  7.     TEST(6-3);  
  8.     TEST(y+3);  
  9. }  

輸出結果:

[cpp] view plaincopyprint?
  1. square of  y is 16.  
  2. square of  6-3 is 9.  
  3. square of  y+3 is 49.  

3.   ##

##運算子可以用於類函式巨集的替換部分.##還可以用於類物件巨集的替換部分.這個運算子可以把兩個語言符號組合成單個語言符號.

例如:

[cpp] view plaincopyprint?
  1. #define XNAME(n) x##n
  2. 執行巨集呼叫:  
  3. int XNAME(4)  
  4. 展開後:  
  5. x4;//相當於直接定義 int x4 這裡也就體現了兩個語言符號的拼接.不過在android經常看到有關##拼接語言符號的情況.