gpt4 book ai didi

c - ## 运算符旁边带有空参数的类函数宏的标准行为?

转载 作者:太空狗 更新时间:2023-10-29 15:01:44 25 4
gpt4 key购买 nike

举个例子:

#define FOO(x) bar x ## baz
FOO( )

根据 ANSI C 和 C99 标准,在预处理阶段之后,上述代码的预期输出是什么?

我通过 gcc -Eclang -E 运行上面的代码,两者都产生了等同于以下内容的输出:

bar baz


另外,如果认为上面的预处理输出是符合标准的,那这个呢?

#define FOO(x) x ## baz
FOO( )

经过上述修改后,GCC 和 clang 仍会产生等同于以下内容的输出,而不会发出任何警告或错误(即使使用 -Wall -Werror 标志):

baz


我怀疑上述输出不符合标准的原因是 ANSI C 9899:1990 标准规定:

6.8.3.3 The ## operator

A ## preprocessing token shall not occur at the beginning or at the end of a replacement list for either form of macro definition.

If, in the replacement list, a parameter is immediately preceded or followed by a ## preprocessing token, the parameter is replaced by the corresponding argument's preprocessing token sequence.

好的,所以技术上 ## 运算符在上面两个例子中都不在替换列表的开头,但是 x 会扩展到……一个空间吗?没有? ...因此 ## 运算符(至少,据我所知)正在将一个空格 pp-token(或什么都没有)连接到 baz


此外,该标准规定:

For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token.

那么,考虑到我在上面给出的第一个示例,为什么正确的输出不应该是这样的呢?

barbaz


更新

作为旁注,在预处理代码时,我确实设法让 GCC 为上面给出的第一个示例发出错误:

gcc -ansi -pedantic -Wall -Werror -E ex1.c -o -

输出(有错误)是:

foo.c:2:6: error: invoking macro FOO argument 1: empty macro arguments are undefined in ISO C90 [-Werror=pedantic]
FOO( )
^
# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "foo.c"

bar baz
cc1: all warnings being treated as errors

但是,该错误与 ## 运算符的行为无关,而这正是该问题的全部内容。尽管如此,它仍然很有趣。

另外值得注意的是,在使用相同的标志预处理文件时,clang 不会发出任何错误。

最佳答案

Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples,

这里的“技术上”这个词是多余的。您的两个宏的替换列表在 ## 之前都有 x,因此该规则不适用。

but x does expand to... a single space? nothing?

6.4 列出了被认为是预处理标记的内容:标题名称、标识符、页数、字符常量、字符串文字、标点符号和“不能​​是上述之一的每个非空白字符”。请注意此列表中明显缺少的内容……空白本身。

所以你在 FOO 参数中的空格并不重要;您的论点是一系列 0 个预处理标记(即上面列表中的 0 个)。这意味着这适用:

6.10.3.3 p2:

however, if an argument consists of no preprocessing tokens, the parameter is replaced by a placemarker preprocessing token instead.

下一段,3,适用于这里的结果:

concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token.

因此,粘贴到 baz 上的 placemarker 生成 baz

关于c - ## 运算符旁边带有空参数的类函数宏的标准行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53387287/

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