- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
举个例子:
#define FOO(x) bar x ## baz
FOO( )
根据 ANSI C 和 C99 标准,在预处理阶段之后,上述代码的预期输出是什么?
我通过 gcc -E
和 clang -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/
我有一个名为 FeedView 的 View ,由 FeedViewController 处理。 我还有一个名为“NearestStore”的 XIB,它由一个名为“NearestStoreViewC
我有一个警报表,其中 tr 元素是使用 JS 动态添加/删除的。问题是它有一个 border-top 将它与上面的内容分开,当表格为空时我想隐藏这些内容。我试过 :empty 和 display:no
我是一名优秀的程序员,十分优秀!