2013-10-05 49 views
11

我有一個程序。C中'#'究竟做了什麼?

#include <stdio.h> 

#define f(a,b) a##b 
#define g(a) #a 
#define h(a) g(a) 

int main() 
{ 
     printf("%s\n",h(f(1,2))); 
     printf("%s\n",g(f(1,2))); 
     return 0; 
} 

該程序正常工作,並給予輸出:

12 
f(1, 2) 

我不明白編譯器如何給這個輸出。

#在a##b#a中有什麼功能?

+0

http://stackoverflow.com/questions/16989730/c-stringify-how-does-it-work –

+0

@YuHao,我真的很抱歉。我搜索了這個問題。我沒有得到任何關聯。因爲我不知道#被稱爲stringify。 – SGG

+0

@SGG嘿,沒關係,因爲很難搜索這個問題,因爲沒有特定的關鍵字。我記得之前看過這個程序,仍然花了幾分鐘的時間來找到重複的東西:)即使知道'#'和'##'的基本用法,這個問題仍然很難得到。 –

回答

4

讓我打破它給你:

#define f(a,b) a##b //2 this macro is evaluated first with a = 1 and b = 2 it concatenates them and returns 12 
#define g(a) #a //4 g turns 12 into "12" (string) 
#define h(a) g(a) //3 back to h which now has a = 12 and call g() 

int main() 
{ 
     printf("%s\n",h(f(1,2)));//1 printf calls the macro h() and gives it the macro f() as an argument 
     printf("%s\n",g(f(1,2)));// g here turns f(1,2) into "f(1,2)" (string) 
     return 0; 
} 
+0

通常是正確的,但是在(1)首先將'h()'定義爲(2),然後「激活」f(),這將是(3),然後是'g()'(4) )。 – glglgl

12

##將兩個令牌連接在一起。

重要的是它只能用在預處理器中。

#運算符用於對令牌進行串聯化。

例如: -

#(a ## b)成爲#ab成爲"ab"

SO 3 H(F(1,2))成爲 「F(1,2)」

還要注意###是兩個不同的運營商。

預處理操作者##提供了一種方法宏膨脹期間來連接實際 參數。如果替換 文本中的參數與##相鄰,則該參數將被實際的 參數替換,會刪除##和周圍的空白區域,並且會重新掃描結果 。

另請檢查此Concatenation瞭解更多詳情。

here: -

字串

有時你可能需要一個宏參數轉換爲字符串常量 。參數不會在字符串常量內被替換,但您可以使用'#'預處理運算符代替。當前導處理程序使用宏參數 時,預處理器將其替換爲實際參數的文本文本,並將其轉換爲字符串常量。 與常規參數替換不同,參數不是首先宏展開的 。這被稱爲字符串化。

沒有辦法將參數與周圍的文本結合起來,並將其全部串聯起來。相反,您可以編寫一系列相鄰的 字符串常量和字符串化參數。預處理器將 替換字符串常量的字符串化參數。然後,編譯器將把所有相鄰的字符串常量合併成一個長度爲1的字符串 。

+0

+1你可能想提一下,'#'和'##'是兩個不同的運算符。 – dasblinkenlight

+0

如果我們有幾乎相同的呼叫,爲什麼結果有所不同? – this

+1

@self。他們如何「幾乎相同」? 2 * 12和2 + 12也是「幾乎相同」併產生完全不同的結果。 – glglgl

4

##被稱爲「令牌粘貼」操作符或「合併」操作符,可用於組合兩個令牌形成實際參數。

#被稱爲「將宏參數轉換爲字符串文字而不擴展參數定義」的字符串化操作符。

這些通常稱爲預處理器操作符。還有一些像這樣的預處理器操作符。查看C中的預處理器運算符(http://msdn.microsoft.com/en-us/library/wy090hkc.aspx)以獲取更多解釋。


而且籤http://msdn.microsoft.com/en-us/library/3sxhs2ty.aspx和頁的關於C預處理的詳細信息,「又見」一節。