define中 與 的神奇用法

2022-07-31 22:03:16 字數 2445 閱讀 7971

本文整理自csdn。

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

#define d(a) #a 

#define s(a) d(a) 

void main( void ) 

輸出結果: 

f(a,b) 

ab分析:  ##把兩個符號連起來 

#a指把a當成符號,就是把#後面的看成字串

# 和 ## 操作符是和#define巨集使用的. 使用# 使在#後的首個引數返回為乙個帶引號的字串. 例如, 命令 

#define to_string( s ) # s 

將會使編譯器把以下命令 

cout < < to_string( hello world! ) < < endl; 

理解為 

cout < < "hello world!" < < endl; 

使用##鏈結##前後的內容. 例如, 命令 

#define concatenate( x, y ) x ## y 

... 

int xy = 10; 

... 

將會使編譯器把 

cout < < concatenate( x, y ) < < endl; 

解釋為 

cout < < xy < < endl; 

理所當然,將會在標準輸出處顯示'10'.

puts(d(f(a,b)));  ----> 因為d巨集中的引數是另外乙個巨集,且帶##,所以作為引數的巨集不展開,相當於 

puts(#f(a,b));----->puts("f(a,b)"); 

puts(s(f(a,b))); ----> 因為s巨集中的引數是另外乙個巨集,但不帶##,所以作為引數的巨集先展開,相當於 

puts(s(ab));----->puts(d(ab));---->puts(#ab);---->puts("ab");

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

#define d(a) #a --》 以"#"開頭的,直接替換,不展開:immediately replaced by the unexpanded actual argument 

#define s(a) d(a) --》 非以"#"開頭的,先展開,再替換,也就是一般的情況 

所以就兩種情況: 

1,不以"#"開頭的,先展開引數a,然後是替換**:puts(s(f(a,b)));-->puts(s(ab))-->puts(d(ab))-->puts("ab") 

2,以"#"開頭的,直接替換,不展開:puts(d(f(a,b)))-->puts("f(a,b)")

#include <

stdio.h

>

#define

direct_literal(a)  #a

#define

indirect_literal(a) direct_literal(a)

intmain(

void) 

這其實從編譯角度的展開歸約也可以理解啊。 

以上**第一種情況,當預編譯器看到direct_literal後查到它是巨集定義,定義為#a,此時後面的引數部分就會以#a的形式生成到原始檔中。也就是說,預編譯後的原始檔中,替代第一條語句的就是: 

puts("indirect_literal(a + b)");輸出則是indirect_literal(a + b) 

而對於第二條語句,當預編譯器看到indirect_literal後查到它是巨集定義,定義為direct_literal(a),這時先把它作為direct_literal(direct_literal(a

+ b))的形式暫存起來,你也可以理解為這個狀態是語法樹的當中乙個葉結點。然後再分析後面的direct_literal後面的引數部分,即:direct_literal(a + b),同樣,預編譯器會將它歸約為"a + b"的形式。這樣對於裡面的direct_literal(a + b)的形式就完全確定下來了,那麼這個值就可以充當葉子結點,即它底下不會再有結點。然後再回到剛才那個狀態,direct_literal("a + b")最後就是"\"a + b\""。所以這裡輸出是"a + b"。 

值得注意的是#a是將引數a轉為字串形式。所以像direct_literal(a)的展開形式是字串常量"a" 

那麼direct_literal("a")展開就是"\"a\""。 

#include 

<

stdio.h

>

#define

direct_literal(a) 

#a#define

indirect_literal(a)

direct_literal(a)

#define

direct_cat(a,

b)   a##b

#define

indirect_cat(a,

b)  direct_cat(a, b)

intmain(

void) 

define中 與 的神奇用法

2009 01 06 10 07 05 分類 linux學習 舉報 字型大小訂閱 本文整理自csdn。define f a,b a b define d a a define s a d a void main void 輸出結果 f a,b ab分析 把兩個符號連起來 a指把a當成符號,就是把 後...

define中 與 的神奇用法

define f a,b a b define d a a define s a d a void main void 輸出結果 f a,b ab分析 把兩個符號連起來 a指把a當成符號,就是把 後面的看成字串 和 操作符是和 define巨集使用的.使用 使在 後的首個引數返回為乙個帶引號的字串....

define中 與 的神奇用法

define f a,b a b define d a a define s a d a void main void 輸出結果 f a,b ab分析 把兩個符號連起來 a指把a當成符號,就是把 後面的看成字串 和 操作符是和 define巨集使用的.使用 使在 後的首個引數返回為乙個帶引號的字串....