天天看點

宏定義中的##

1、在一個預處理器宏中的參數前面使用一個#,預處理器會把這個參數轉換為一個字元數組。(原文:When you put a # before an argument in a preprocessor

macro, the preprocessor turns that argument into a character array. This,

combined with the fact that character arrays with no intervening punctuation are concatenated into a single character array, allows you to make a very convenient macro for printing the values of variables during debugging)

#include "iostream"

using namespace std;

#define P(A) cout<<#A<<": "<<(A)<<endl;

int main()

{

int a=1,b=2;

P(a);

P(b);

P(a+b);

return 1;

}

http://blog.163.com/zhoumhan_0351/blog/static/39954227201032124942513/

2、#define D(a) cout << #a "=[" << a << "]" << endl;

3、#是“字元串化”的意思。出現在宏定義中的#是把跟在後面的參數轉換成一個字元串

例如:

           > #define  FOO(arg)   my##arg

       則

           > FOO(abc)

       相當于   myabc

           > #define STRCPY(dst, src)   strcpy(dst, #src)

           > STRCPY(buff, abc)

       相當于   strcpy(buff, "abc")

另外,如果##後的參數本身也是一個宏的話,##會阻止這個宏的展開,也就是隻替換一次。

   #define STRCPY(a, b)    strcpy(a ## _p, #b)

   int main()

   {

       char var1_p[20];

       char var2_p[30];

        /* 注意這裡 */

       STRCPY(STRCPY(var1,var2),var2);

       /* 這裡是否會展開為: strcpy(strcpy(var1_p,"var2")_p,"var2“)?

        * 答案是否定的:

        * 展開結果将是:  strcpy(STRCPY(var1,var2)_p,"var2")

        * ## 阻止了參數的宏展開!

        * 如果宏定義裡沒有用到 # 和 ##, 宏将會完全展開

        */

   }  

http://blog.chinaunix.net/u/17855/showart_113663.html

4、about ## in common text

(1)關于記号粘貼操作符(token paste operator): ##

簡單的說,“##”是一種分隔連接配接方式,它的作用是先分隔,然後進行強制連接配接。

其中,分隔的作用類似于空格。我們知道在普通的宏定義中,預處理器一般把空格解釋成分段标志,對于每一段和前面比較,相同的就被替換。但是這樣做的結果是,被替換段之間存在一些空格。如果我們不希望出現這些空格,就可以通過添加一些##來替代空格。

另外一些分隔标志是,包括操作符,比如 +, -, *, /, [,], ...,是以盡管下面的

宏定義沒有空格,但是依然表達有意義的定義: define add(a, b)  a+b

而其強制連接配接的作用是,去掉和前面的字元串之間的空格,而把兩者連接配接起來。

(2)舉列 -- 試比較下述幾個宏定義的差別

#define A1(name, type)  type name_##type##_type 或

#define A2(name, type)  type name##_##type##_type

A1(a1, int);  /* 等價于: int name_int_type; */

A2(a1, int);  /* 等價于: int a1_int_type;   */

解釋:

1) 在第一個宏定義中,"name"和第一個"_"之間,以及第2個"_"和第二個"type"之間沒有被分隔,是以預處理器會把name_##type##_type解釋成3段:

“name_”、“type”、以及“_type”,這中間隻有“type”是在宏前面出現過

的,是以它可以被宏替換。

2) 而在第二個宏定義中,“name”和第一個“_”之間也被分隔了,是以

預處理器會把name##_##type##_type解釋成4段:“name”、“_”、“type”

以及“_type”,這其間,就有兩個可以被宏替換了。

3) A1和A2的定義也可以如下:

#define A1(name, type)  type name_  ##type ##_type

<##前面随意加上一些空格>

#define A2(name, type)  type name ##_ ##type ##_type

結果是## 會把前面的空格去掉完成強連接配接,得到和上面結果相同的宏定義

(3)其他相關 -- 單獨的一個 #

至于單獨一個#,則表示對這個變量替換後,再加雙引号引起來。比如

#define  __stringify_1(x)   #x

那麼

__stringify_1(linux)   <==>  "linux"

(5)#(stringizing)字元串化操作符。其作用是:将宏定義中的傳入參數名轉換成用一對雙引号括起來參數名字元串。其隻能用于有傳入參數的宏定義中,且必須置于宏定義體中的參數名前。

如:

#define example(instr) printf("the input string is:\t%s\n",#instr)

#define example1(instr) #instr

當使用該宏定義時:

example(abc); 在編譯時将會展開成:printf("the input string is:\t%s\n","abc");

string str=example1(abc); 将會展成:string str="abc";

注意:

對空格的處理

a。忽略傳入參數名前面和後面的空格。

如:str=example1(   abc ); 将會被擴充成 str="abc";

繼續閱讀