gpt4 book ai didi

c - 为什么 MSVC 预处理器连接 token 的方式与 GCC 和 Clang 不同?

转载 作者:行者123 更新时间:2023-12-03 09:30:57 25 4
gpt4 key购买 nike

最近,我遇到了 MSVC 的问题。这是一个最小的例子。

#define NUMBERSIGNS(a,b) a##b
#define CONCAT(a,b) NUMBERSIGNS(a,b)
#define AA
#define BB
CONCAT(B, CONCAT(A, A B))
我在想什么:
由于参数在 ## 之前或之后不会扩展,我需要一个 NUMBERSIGNS(a,b)宏来结束 ## ,并用 CONCAT(a,b) 调用它,因此参数在连接之前会被扩展。
CONCAT(B, CONCAT(A, A B))得到扩展,我希望内部 CONCAT(A, A B)扩展为 AA B , 屈服 CONCAT(B, AA B) .
然后我们展开 AA 我们得到 CONCAT(B, B) (我猜MSVC没有做这一步,不知道是不是应该)。
然后我们有 BB重新扫描并扩展为 .
由 gcc 和 clang 预处理的代码产生空,这是我想要的结果:

而 MSVC 给出:
BAA B
这是 MSVC 的错误还是我正在编写未定义的行为?
编辑:

Thanks to the answers, where the problem was has been identified. MSVC did not conform to the Standard.

However, recently it seems they started to take the Standard seriously and added a new /Zc:preprocessor option to enable a full conforming mode of their C/C++ preprocessor. See:Announcing full support for a C/C++ conformant preprocessor in MSVC

最佳答案

C 2018 6.10.3.1 1 指定宏参数替换:

After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded. Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available.



CONCAT ( B , CONCAT ( A , A B ) ) ,第一 CONCAT宏有参数 BCONCAT ( A , A B ) .这些参数首先被完全宏替换。
B不是宏,所以它仍然是 B .

CONCAT ( A , A B ) , 参数 AA B被完全宏替换,但它们不是宏,所以它们仍然是 AA B .

然后 CONCAT ( A , A B )NUMBERSIGNS 取代 ( A , A B ) .

然后 6.10.3.4 1 告诉我们:

After all parameters in the replacement list have been substituted and # and ## processing has taken place, all placemarker preprocessing tokens are removed. The resulting preprocessing token sequence is then rescanned, along with all subsequent preprocessing tokens of the source file, for more macro names to replace.



所以 NUMBERSIGNS ( A , A B )A 取代 ## A B .然后是 ##前后的token连接在一起,形成 AA B (根据 6.10.3.3 3)。

这个序列 AA B然后根据 6.10.3.4 1 再次重新扫描。由于 AA是一个宏,它被替换为没有标记,只留下 B .这样就完成了第一个 CONCAT 的第二个参数的展开.

因此,在参数替换之后,我们有 CONCAT ( B , B ) .

现在 CONCAT被替换,形成 NUMBERSIGNS ( B , B ) .

NUMBERSIGNS是一个宏,这被替换为 B ## B .然后是 ##前后的token连接在一起,形成 BB .

这是重新扫描,和 BB被替换为没有 token 。

最终结果是没有 token 。 GCC是正确的,MSVC的结果不符合C标准。

关于c - 为什么 MSVC 预处理器连接 token 的方式与 GCC 和 Clang 不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62363585/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com