簡體   English   中英

擴展類似函數的宏會創建一個單獨的標記

[英]Expansion of function-like macro creates a separate token

我剛剛發現gcc似乎將類似函數的宏的擴展結果視為一個單獨的標記。 這是一個顯示gcc行為的簡單示例:

#define f() foo
void f()_bar(void);
void f()bar(void);
void f()-bar(void);

當我執行gcc -E -P test.c (只運行預處理器)時,我得到以下輸出:

void foo _bar(void);
void foo bar(void);
void foo-bar(void);

看起來,在前兩個定義中,gcc在擴展宏之后插入空格以確保它是一個單獨的標記。 這真的發生在這里嗎?

這是否由任何標准強制執行(我找不到關於該主題的文檔)?

我想讓_bar成為同一個標記的一部分。 有沒有辦法做到這一點? 我可以使用令牌連接運算符##但它需要幾個級別的宏(因為在實際代碼中f()更復雜)。 我想知道是否有一個簡單的(可能更具可讀性)解決方案。

我能想到的唯一方法(如果你不能使用令牌連接運算符##)是使用傳統的(預標准)C預處理:

gcc -E -P -traditional-cpp test.c

輸出:

void foo_bar(void);
void foobar(void);
void foo-bar(void);

更多信息

看起來,在前兩個定義中,gcc在擴展宏之后插入空格以確保它是一個單獨的標記。 這真的發生在這里嗎?

是。

這是否由任何標准強制執行(我找不到關於該主題的文檔)?

是的,雖然允許實現插入甚至多個空格來分隔令牌。

f()_bar

在詞法分析之后你有4個令牌(它們在這個階段實際上是預處理器令牌但是讓它們稱為令牌): f()_bar

類似函數的宏替換語義(如C11,6.10.3中所定義)必須將3個標記f()替換為新的foo 不允許在其他令牌上工作並更改最后一個_bar令牌。 為此,實現必須插入至少一個空格以保留_bar標記。 否則結果將是foo_bar ,這是一個單一的標記。

gcc預處理器在這里有點記錄

一旦輸入文件被分解為標記,標記邊界就不會改變,除非使用'##'預處理運算符將標記粘貼在一起。 請參見連接。 例如,

 #define foo() bar foo()baz ==> bar baz not ==> barbaz 

在另一種情況下,就像f()-bar ,有5個標記: f()-bar -是C中的標點符號,而_bar _只是標識符標記的字符)。 實現不必在此處插入標記分隔符(如空白),因為宏替換后-bar仍被視為來自C語法的兩個獨立標記。

gcc預處理器( cpp )不會在這里插入空格,因為它不需要。 cpp 文檔中 ,在令牌間隔上寫入(在不同的問題上):

但是,我們希望將空間插入保持在最低限度,這既是出於美學原因,又是因為它仍然會導致仍然試圖濫用Fortran源和Makefile等預處理器的人員出現問題。

我沒有在這個答案中解決你的問題的解決方案,但我認為你必須使用顯式指定的運算符來連接標記: ## token貼標操作符。

暫無
暫無

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

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