C++ 在宏参数中使用#line指令合法吗?

C++ 在宏参数中使用#line指令合法吗?,c++,c,visual-studio,gcc,C++,C,Visual Studio,Gcc,我注意到这个程序是用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': undeclar

我注意到这个程序是用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接受代码?

它是无效的。行为未定义,因此不需要诊断,允许实现接受代码

根据C标准,6.10.3宏替换:

11[…]如果参数列表中有一系列预处理标记,这些标记将用作预处理指令,则该行为未定义


C++标准包含16.3个宏替换中的完全相同的单词。

< P>如果编译了所有警告的示例,GCC给出:

警告:在宏参数中嵌入指令是不可移植的

叮当声给了你:

警告:在宏参数中嵌入指令具有未定义的行为


这明确地向我表明,这种行为确实是未定义的

#行在标准中,但可能是Visual studio试图将“#line 3\”test1.c\“\n0\n”输入宏,而GCC在将#行输入XT之前对其进行评估,以确保严格无需进行诊断,因为此段在语义部分中。例如,约束部分中明确的未定义行为需要诊断,如5.1.1.3诊断:
如果预处理翻译单元或翻译单元违反任何语法规则或约束,即使行为也明确指定为未定义或实现定义
@GrzegorzSzpetkowski,也没有任何约束给出规则,如果违反规则,则表示行为未定义。我认为5.1.1.3指的是具有独立错误、一些违反约束和其他未定义行为的程序。这确实有道理,特别是因为“实现定义”的行为,在Constant中也从未遇到过。