簡體   English   中英

gcc和Microsoft預處理器之間的區別

[英]Difference between gcc and Microsoft preprocessor

我發現Microsoft Visual Studio編譯器和gcc以不同的方式預處理以下小片段:

# define M3(x, y, z) x + y + z
# define M2(x, y) M3(x, y)
# define P(x, y) {x, y}
# define M(x, y) M2(x, P(x, y))
M(a, b)

'gcc -E'給出以下內容:

a + {a + b}

,'cl / E'發出關於缺少宏參數的警告並產生以下輸出:

a + {a, b} +

似乎來自嵌套宏擴展的逗號不被視為參數分隔符。 不幸的是,我沒有找到cl預處理器中實現的算法的描述,所以我不確定我的建議是否正確。 有誰知道cl預處理器是如何工作的,它的算法和gcc之間有什么區別? 以及如何解釋觀察到的行為?

# define M3(x, y, z) x + y + z
# define M2(x, y) M3(x, y)
# define P(x, y) {x, y}
# define M(x, y) M2(x, P(x, y))
M(a, b)

讓我們一步一步地手動推出:

M(a, b)
--> M2(a, P(a, b))
--> M2(a, {a, b})

標准說:

列表中的各個參數由逗號預處理標記分​​隔,但匹配內部括號之間的逗號預處理標記不會分開

只提到括號,所以......

--> M3(a, {a, b})
--> a + {a + b}

重要:

M3(a, {a, b})

在這里,根據標准的先前引用,三個“參數”被傳遞給M3(使用單引號來描述標記/參數):

M3('a', '{a', 'b}')

這些擴展到了

'a' + '{a' + 'b}'

這就是cpp (4.6.1)逐字提供的內容:

# 1 "cpp.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "cpp.cpp"




a + {a + b}

cpp (或gccg++ )是正確的,MSVC不是。

作為貴族,請確保存在錯誤報告。

解釋這種行為的唯一邏輯就是這樣。

CL方式:

 M(a,b) 
 M2(a,P(a,b)) 
 M3(a,P(a,b))
 M3(a,{a,b}) -> M3 gets 2 arguments ( 'a' and '{a,b}') instead of 3.
    |  \ /
  arg1  |
      arg2 

Gcc方式:

M(a,b) 
M2(a,P(a,b)) 
M3(a,P(a,b))
M3(a,{a,b}) -> Gcc probably thinks there are 3 arguments here ('a', '{a', 'b}').
   |  | |
 arg1 | |
   arg2 |
     arg3

我認為gcc做對了,微軟做的不對。

當對該行進行宏替換時

M2(a, P(a, b))

標准(第6.10.3.1節)要求在用其參數(“P(a,b)”)替換宏的替換列表(“M3(x,y)”)中的第二個參數(“y”)之前,宏對該論點進行替換。 這意味着“P(a,b)”在插入之前被處理為“{a,b}”,從而產生

M3(a, {a, b})

然后進一步替換為

a + {a + b}

暫無
暫無

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

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