2011-07-04 52 views
2

我在C東西像這樣定義一個宏:原始的#define理解用C

#define SOME_FIELD(_A_,_B_,_C_) \ 
    MyObj[ ## _A_ ## ].somePTR =  \ 
    (DWORD_PTR) (buff_ ## _C_ ## _C_ ## _ ## _B_ ##); 

我可以理解,對於指數一個我們正在爲「somePTR」一些價值。我的問題是,什麼是## <name> ##符號和這somePTR的價值如何計算?

我對這樣的宏很陌生,所以描述性解釋會非常有幫助。

+0

爲什麼不僅僅是一個示例並檢查預處理器輸出? 'gcc -E'等 –

+0

我希望那些不是params和宏的實際名稱......如果是這樣的話,作者需要一些同情心培訓。 – Dennis

+0

@丹尼斯 - 這些不是真正的名字,這個宏是一個可怕的宏觀的簡化形式。 – HokageSama

回答

7

這就是所謂的token concatenation。它允許你將參數粘合在一起。

對於你的榜樣,SOME_FIELD(Param1,Param2,Param3);擴展這樣的:

MyObj[Param1].somePTR = (DWORD_PTR) (buff_Param3Param3_Param2); 

這是很容易使用你的編譯器的預處理器嘗試了這一點自己。你通常不需要去編寫一個完全成熟的C程序 - 預處理器通常可以自行調用。

+0

謝謝Dav。這有幫助。 – HokageSama

1

的##讀它concatenation原始的,它是用來創建nwe符號。

這是非常有用的宏創建名稱:

#define GENERIC_GETTER(f,g) (g->member_ ## f) 

GENERIC_GETTER(a,b)將創建(b->member_a)(創建新的符號)。如果您不要用尖銳鋒利,它會創建(b->member_ a)(未粘在一起)

1

通常情況下,##運算符連接兩個令牌:它需要在左側和右側的法律令牌的法律 令牌,和會產生一個新的令牌 。在你的情況下,宏 (MyObj[&nbsp;##&nbsp;_A_&nbsp;##&nbsp;].somePtr&nbsp;=&nbsp;\)中的第一行是 非法,並導致未定義的行爲。大多數實現只是 連接字符串,然後一旦他們完成了所有 替換,retokenize,所以它會工作,但它不能保證。至於我在這裏可以告訴的 ,這沒有必要。在第二行中,另一方面,您正在生成新的令牌。如果你調用宏:

SOME_FIELD(x,y,z); 

將擴大到:

MyObj[x].somePtr = (DWORD_PTR)(buff_zzy); 

(我想補充一點,像_A__B__C_符號的使用也 不確定的行爲符號開始。下劃線後面跟着一個大寫字母 位於實現的命名空間中。)

+0

你指出了很多事情是正確的。感謝您花時間解釋它們。 – HokageSama