簡體   English   中英

在宏中展開宏

[英]Expand a macro in a macro

給定以下宏以函數調用方式訪問編譯器屬性,例如spec(section(".mysection")) void foo(void);

#define spec(_H_) spec_##_H_
#define spec_section(_S_) attribute ((section (_S_)))

我現在想在其他宏中使用這些定義,例如spec(namespace(unmanaged)) int x;

#define spec_namespace(_H_) spec_namespace_##_H_
#define spec_namespace_unmanaged spec(section(".unmanaged"))

但這根本沒有擴展,使其工作的唯一方法是自己編寫擴展的 spec() 宏:

#define spec_namespace_unmanaged spec_section(".unmanaged")

知道發生了什么嗎? gcc -E on spec(namespace(unmanaged))導致spec(namespace(unmanaged))

引用C99草案6.10.3.4 重新掃描和進一步替換 §2(強調我的):

如果在替換列表的掃描期間找到了要替換的宏的名稱(不包括源文件的其余預處理令牌),則不會替換該宏。 此外,如果任何嵌套的替換遇到要替換的宏的名稱, 則不會替換它。 這些未替換的宏名稱預處理令牌不再可用於進一步替換,即使它們后來在本來會被替換的宏名稱預處理令牌的上下文中進行了(重新)檢查。

根據以下宏定義:

#define spec(_H_) spec_##_H_
#define spec_namespace(_H_) spec_namespace_##_H_
#define spec_namespace_unmanaged spec(section(".unmanaged"))

顯然, spec宏被評估了兩次,因此沒有進一步的替換,讓我們逐步進行:

spec(namespace(unmanaged)) int x; → spec_namespace(unmanaged) int x;
spec_namespace(unmanaged) int x;  → spec_namespace_unmanaged int x;
spec_namespace_unmanaged int x;   → spec(section(".unmanaged")) int x;

您可以做的就是將您的最后一個宏定義修改為以下形式:

#define spec_namespace_unmanaged attribute ((namespace (".unmanaged")))

或簡化為:

#define spec(_H_) spec_##_H_
#define spec_section(_S_) attribute ((section (_S_)))
#define spec_namespace(_N_) attribute ((namespace (_N_)))

有:

spec(namespace(".unmanaged")) int x;

簡而言之,如果在右側(在宏定義中)沒有將字符串化運算符#和連接運算符##應用於它,預處理器只會在左側(在另一個宏的參數中)擴展嵌套宏。

強制嵌套宏擴展的慣用方法是使用輔助宏:

#define macro_helper(x) macro(x) // gets x expanded

考慮以下示例,該示例擴展了嵌套的__LINE__宏:

#include <iostream>

#define MACRO1(L)   "Line " #L         // MACRO1(__LINE__) -> "Line " "__LINE__")
#define MACRO2       MACRO1(__LINE__)  // MACRO2 -> MACRO1(__LINE__)

#define MACRO3(L)   "Line " #L         // MACRO3(13) -> "Line " "13")
#define MACRO4(L)   MACRO3(L)          // MACRO4(__LINE__) -> MACRO3(13)
#define MACRO5      MACRO4(__LINE__)   // MACRO5 -> MACRO4(__LINE__)

int main()
{
    std::cout << MACRO2 << std::endl;  // Output: "Line __LINE__"
    std::cout << MACRO5 << std::endl;  // Output: "Line 13"
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM