簡體   English   中英

GCC和VC ++預處理程序的意外行為

[英]Unexpected Behaviour of GCC and VC++ Preprocessor

我試圖了解C ++標准預處理程序的要求。 我創建的一個棘手的示例在GCC和VC ++ 2010中產生了令人驚訝的結果:

#define a(x,y) x##y
#define tzsW kka
a(t,zs  )W

GCC產量:

tzs W

請注意在W之前添加的額外空間。

VC ++ 2010收益:

tzsW

請注意,在W之前沒有添加空格,但是標識符沒有進一步擴展。 我掃描了C ++ 03標准,但找不到任何內容說明我們應該像在gcc中那樣防止創建新的標識符( tzsW )。 而且沒有什么能阻止這個新的標識符進一步擴展宏了(VC ++行為)。

為什么GCC和VC ++ 2010不喜歡新的標識符?

編輯

如果使用了另一個宏調用,例如

a(t,zs  )[]

gcc產量:

tzs[]

請注意,未添加任何空間,顯示gcc故意為我之前的案例添加了空間。

預處理器的輸出是令牌,而不是純文本。 除非您使用令牌粘貼運算符,否則在預處理中通常不會合並令牌。

當您查看預處理步驟的輸出時,必須將標記轉換為文本。 gcc插入了空格,因此您不會誤認為tzsW是單個令牌。 不需要在tzs[情況下執行此操作,因為[不是有效的標識符字符,因此不會造成混淆。

兩種編譯器都沒有將tzsW視為要重新擴展的單個令牌是正確的。

請注意, Visual C ++文檔承認,與將原始源進行編譯相比,編譯預處理器的輸出可能會產生不同且錯誤的輸出,這是因為在將預處理的輸出轉換為文本時,它們不會插入空格來分隔標記。 當在正常操作中將預處理器輸出直接傳遞到編譯器的下一級時,不會發生這種情況。

  1. 空間還是沒有空間?

    我沒有在標准中找到參考,但是本文討論了這個問題。 簡而言之,決定是否要這個空間並不容易...

  2. 更換tzsWkka與否?

    參見標准中的16.3.4:

    替換了替換列表中的所有參數后,將使用源文件的所有后續預處理令牌重新掃描所得的預處理令牌序列,以替換更多的宏名。

    這表明VC的行為在此處不正確。

暫無
暫無

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

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