是否可以定义另一个预处理器指令?

ST3*_*ST3 20 c c++ c-preprocessor preprocessor-directive

我一直在寻找代码高尔夫,并有一个想法尝试这个代码:

#define D #define 添加此行后,一切正常,但我将其扩展为:

#define D #define
D VALUE
Run Code Online (Sandbox Code Playgroud)

在这里我得到了5个编译错误.如果我D改成#define一切都很好,有人可以解释一下,为什么这段代码是非法的?

注意: 我使用的是VS2008编译器.

编辑: 经过一些答案,我看到我需要给出编译错误列表:

  1. 错误C2121:'#':无效字符:可能是宏扩展的结果
  2. 错误C2146:语法错误:缺少';' 在标识符"VALUE"之前
  3. 错误C4430:缺少类型说明符 - 假定为int.注意:C++不支持default-int
  4. 错误C2144:语法错误:'void'前面应加';'
  5. 错误C4430:缺少类型说明符 - 假定为int.注意:C++不支持default-int

第一个错误显示D不仅是define,还包括#.

Eri*_*hil 31

C 2011(N1570)6.10.3.4 3:"得到的完全宏替换的预处理标记序列不会被处理为预处理指令,即使它类似于一个......"

C++ 2010(N3092)16.3.4 [cpp.rescan] 3具有完全相同的文本.

  • 这是正确的答案.C语言标准指定了程序源代码的翻译操作的确切顺序. (2认同)

Car*_*rum 10

看起来您的预处理器正在进行您想要的替换,但您可能无法获得所需的行为 - 预处理器通常只是单个传递操作.示例(使用clang,但您应该能够使用适当的VS2008标志重现):

$ cat example.c 
#define D #define
D VALUE
$ cc -P -E example.c 

 #define VALUE
Run Code Online (Sandbox Code Playgroud)

#define VALUE将直接进入编译器,编译器将不知道如何处理它 - 毕竟它是一个预处理器指令.Clang的错误,供参考,与您的相似:

$ cc -c example.c 
example.c:2:1: error: expected identifier or '('
D VALUE
^
example.c:1:11: note: expanded from macro 'D'
#define D #define
          ^
1 error generated.
Run Code Online (Sandbox Code Playgroud)

  • 预处理器是否是单通道操作是无关紧要的.预处理器不需要对文件进行多次扫描,以便重新处理单个行; 它可以根据需要多次处理每一行.实际上,它确实这样做:重复执行宏替换.宏替换后不处理预处理程序指令的原因是因为语言标准不这样做. (15认同)

AnT*_*AnT 10

此代码是非法的,因为语言规范说它是非法的.根据C和C++预处理器规范,使用预处理器构建的任何代码都不会被解释为另一个预处理器指令.简而言之,您无法使用预处理器构建预处理程序指令.期.

(另外,您无法使用预处理器构建注释.)


Lar*_*Pel 6

这是行不通的,因为预处理是在一次通过中执行的.例如,考虑下一个代码:

#define MYDEFINEWEIRD #define

MYDEFINEWEIRD N 6

int main() {

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

预处理后,您的代码将如下所示:

 #define N 6
int main() {

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

和"#define"不是C或C++上的有效语法.此外,由于不会处理生成的预处理程序指令,因此它不会解析代码中对"N"宏的后续引用.

只是为了好玩,您可以使用g ++/gcc从命令行调用预处理器两次.考虑下一个代码(define.cpp):

#include <iostream>

#define MYDEFINEWEIRD #define
MYDEFINEWEIRD N 6

using namespace std;

int main() {
  cout << N << endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

$ g++ -E define.cpp | g++ -o define -x c++ - && ./define
Run Code Online (Sandbox Code Playgroud)

并将输出:

6
Run Code Online (Sandbox Code Playgroud)

  • "预处理是在一次通过中执行的" - 不,实际上它不是 - 这不是**错误的原因. (2认同)
  • @ H2CO3,我认为这个答案的结果看起来是正确的. (2认同)