瞭解宏擴展
回答
EDIT
3.9.6參數預掃
宏參數是完全宏擴展它們是 代入宏體之前,除非它們被字符串化或與其他令牌粘貼 。替換之後,將再次掃描包括替換參數在內的整個宏體 ,宏將擴展爲 。結果是參數被掃描兩次以在其中擴展 宏調用。
調用其他宏的字符串化或連接的宏。如果 參數被字符串化或級聯,則不會發生預掃描。 如果您想要展開宏,然後將其展開或連接其擴展,可以通過使一個宏調用另一個執行串化或串聯的宏 來實現。
舉例來說,如果你有
#define AFTERX(x) X_ ## x
#define XAFTERX(x) AFTERX(x)
#define TABLESIZE 1024
#define BUFSIZE TABLESIZE
然後AFTERX(BUFSIZE)擴展到X_BUFSIZE,並XAFTERX(BUFSIZE)擴展到X_1024。 (不X_TABLESIZE。預掃描總是做了完整的擴展。)
CASE1
#define JOIN__(lhs, rhs) lhs##rhs
=>因爲它有一個標記粘貼操作者,它會連接這些宏參數那些不完全宏觀膨脹前取代。 - >這是一種糟糕的擴展方式,我們不知道的第一個地方,它將傳遞給它的參數是什麼,它不會等待它的擴展,而只是將它連接起來。
因此,當您撥打JOIN__(Foo, JOIN(A,B));
時,它將不允許JOIN(A,B)
展開,並將它連接到FOOJOIN(A,B)。
CASE2 現在,在另一方面, #define JOIN_(lhs, rhs) JOIN__(lhs, rhs)
=>這裏,沒有標記粘貼操作,宏參數是完全宏擴展它們代入宏體之前。因此,它將允許lhs和rhs擴展並且用擴展參數JOIN__(FOO,AB)
來調用,因此現在JOIN__具有令牌粘貼操作符,它將簡單地連接它的參數FOO和AB即FOOAB。這是做到這一點的適當方式。
CASE3 #define JOIN(lhs, rhs) JOIN_(lhs, rhs)
=>與CASE2相同。
希望能解釋一下多級擴展範例背後的原因。
ORIGINAL 預處理運算符##提供了一種在宏擴展期間連接實際參數的方法。如果替換文本中的參數與##相鄰,則該參數將被實際參數替換,將刪除##和周圍的空白區域,並重新掃描結果。例如,宏粘貼連接它的兩個參數:
#define paste(front, back) front ## back
so paste(name, 1) creates the token name1.
我知道令牌粘貼操作符。我在詢問這種多級擴展範例,而不是級聯 –
@AndréFratelli:請查找「多級擴展範例」的更新答案。希望它解釋你在找什麼。 –
真棒回答,真的很徹底。 –
的##
記號化操作不計算(宏展開)它的參數。函數式的宏擴展do然而,評估參數,這就是爲什麼你得到預期(評估)輸出的第一種情況。
技術上,宏JOIN_
是不必要的,因爲在JOIN
lhs
和rhs
擴大JOIN__
時被評估。這將是足夠的:
#define JOIN(lhs, rhs) JOIN__(lhs, rhs)
#define JOIN__(lhs, rhs) lhs##rhs
我真的找不到你錯了的情況,但爲什麼代碼會這樣寫呢? –
請參閱我的編輯。我包含了原始代碼 –
@AndréFratelli - 誰知道?人們會做一些奇怪的事情......但我認爲沒有任何理由將代碼編寫成這種方式。 – owacoder
- 1. 定義宏擴展到了文字#
- 2. __VA_ARGS__宏擴展
- 3. Verilog宏擴展
- 4. 宏擴展
- 5. Unfamilar宏擴展
- 6. 瞭解Firefox擴展代碼
- 7. 瞭解Firefox擴展結構
- 8. MSVC++ variadic宏擴展
- 9. 快速宏擴展
- 10. 超載宏擴展
- 11. 延遲宏擴展
- 12. 禁止宏擴展
- 13. C/C++宏擴展
- 14. C++宏擴展器
- 15. Clojure的宏擴展
- 16. 跟蹤宏擴展
- 17. 瞭解_countof宏
- 18. 宏擴展到額外的宏參數
- 19. 擴展了PHP
- 20. 在遞歸擴展宏
- 21. C++宏擴展,調試
- 22. 預編譯可擴展宏
- 23. 錯誤用c宏擴展
- 24. C宏擴展說明
- 25. moc中的宏擴展
- 26. 包宏擴展方法
- 27. qtcreator + gdb,擴展宏定義
- 28. 擴展C宏的類型
- 29. Eclipse宏擴展顏色
- 30. NSString內部的宏擴展
我認爲,最後一個宏'JOIN __(Foo,JOIN(A,B));'應該擴展爲'FooJOIN(A,B)'而不只是'FooJOIN',請澄清。 –
這是可能的。我得到'警告:函數'FooJOIN'的隱式聲明在C99'中是無效的,所以我真的不知道它得到了哪些參數。但是你的意思是有道理的 –