在宏参数中使用 #line 指令是不是合法?
Posted
技术标签:
【中文标题】在宏参数中使用 #line 指令是不是合法?【英文标题】:Is it legal to use the #line directive in a macro argument?在宏参数中使用 #line 指令是否合法? 【发布时间】:2015-02-05 12:04:10 【问题描述】:我注意到这个程序是用 gcc 编译的:
#define X(A) A
int x = X(
#line 3 "test1.c"
0
);
然而,Visual Studio 编译失败:
main.cpp
main.cpp(6): error C2121: '#': invalid character: possibly the result of a macro expansion
main.cpp(6): error C2065: 'line': undeclared identifier
main.cpp(6): error C2143: syntax error: missing ';' before 'constant'
main.cpp(6): error C2059: syntax error: 'constant'
我想知道:该程序是否合法,或者它是否默默地依赖未定义(或实现定义)的行为而恰好使 gcc 接受代码?
【问题讨论】:
#line 在标准中,但可能是 Visual Studio 尝试将 "#line 3 \"test1.c\"\n0\n" 输入宏,而 GCC 评估 #在将其输入 X 之前的行 【参考方案1】:无效。该行为是未定义的,因此不需要诊断,并且允许实现接受代码。
从 C 标准,6.10.3 宏替换:
11 [...] 如果参数列表中存在预处理标记序列,否则它们将充当预处理指令,则行为未定义。
C++ 标准在 16.3 宏替换中包含这些完全相同的词。
【讨论】:
严格来说不需要诊断,因为这一段在语义部分。例如,Constraints 部分中的显式未定义行为需要诊断,如 5.1.1.3 诊断:if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as undefined or implementation-defined
.
@GrzegorzSzpetkowski 在任何地方都没有给出规则的约束,并且如果违反规则,则表示行为未定义。我认为 5.1.1.3 指的是具有单独的独立错误、一些违反约束和其他未定义行为的程序。
这真的很有意义,尤其是因为“实现定义的”行为,在约束中也从未遇到过。【参考方案2】:
如果你编译带有所有警告的示例,gcc 会给你:
警告:在宏参数中嵌入指令不可移植
clang 给你:
警告:在宏参数中嵌入指令具有未定义的行为
这绝对强烈地向我表明该行为确实是未定义的。
【讨论】:
以上是关于在宏参数中使用 #line 指令是不是合法?的主要内容,如果未能解决你的问题,请参考以下文章