简体   繁体   English

gcc和Microsoft预处理器之间的区别

[英]Difference between gcc and Microsoft preprocessor

I discovered that Microsoft Visual Studio compiler and gcc preprocess the following small snippet differently: 我发现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' gives the following: 'gcc -E'给出以下内容:

a + {a + b}

, while 'cl /E' issues a warning about missing macro argument and produces the following output: ,'cl / E'发出关于缺少宏参数的警告并产生以下输出:

a + {a, b} +

It seems that commas that came from nested macro expansions are not considered to be argument separators. 似乎来自嵌套宏扩展的逗号不被视为参数分隔符。 Unfortunately, I found no description of the algorithm implemented in cl preprocessor, and so I'm not sure that my suggestion is correct. 不幸的是,我没有找到cl预处理器中实现的算法的描述,所以我不确定我的建议是否正确。 Does anyone know how cl preprocessor works and what's the difference between its algorithm and gcc's? 有谁知道cl预处理器是如何工作的,它的算法和gcc之间有什么区别? And how the observed behaviour can be explained? 以及如何解释观察到的行为?

# 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)

Let us roll this out manually, step by step: 让我们一步一步地手动推出:

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

The standard says: 标准说:

The individual arguments within the list are separated by comma preprocessing tokens, but comma preprocessing tokens between matching inner parentheses do not separate 列表中的各个参数由逗号预处理标记分​​隔,但匹配内部括号之间的逗号预处理标记不会分开

only parentheses are mentioned, so ... 只提到括号,所以......

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

Important: 重要:

M3(a, {a, b})

Here, according to the previous quote from the standard, three "arguments" are passed to M3 (using single-quotes to describe tokens/arguments): 在这里,根据标准的先前引用,三个“参数”被传递给M3(使用单引号来描述标记/参数):

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

which are expanded to 这些扩展到了

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

And this is what cpp (4.6.1) gives verbatim: 这就是cpp (4.6.1)逐字提供的内容:

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




a + {a + b}

cpp (or gcc and g++ ) are correct, MSVC isn't. cpp (或gccg++ )是正确的,MSVC不是。

As a nobleman make sure a bug report exists. 作为贵族,请确保存在错误报告。

The only logic that explains such a behavior looks like this. 解释这种行为的唯一逻辑就是这样。

CL way: 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 way: 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

I think gcc gets it right, what Microsoft does is incorrect. 我认为gcc做对了,微软做的不对。

When macro substitution is done for the line 当对该行进行宏替换时

M2(a, P(a, b))

the standard (section 6.10.3.1) requires that before replacing the second parameter ("y") in the macro's replacement list ("M3(x, y)") with its argument ("P(a, b)"), macro replacement is to be performed for that argument. 标准(第6.10.3.1节)要求在用其参数(“P(a,b)”)替换宏的替换列表(“M3(x,y)”)中的第二个参数(“y”)之前,宏对该论点进行替换。 This means "P(a, b)" is processed to "{a, b}" before it is inserted, resulting in 这意味着“P(a,b)”在插入之前被处理为“{a,b}”,从而产生

M3(a, {a, b})

which is then further replaced to 然后进一步替换为

a + {a + b}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM