【问题标题】:Is there a way to escape a C preprocessor directive?有没有办法逃避 C 预处理器指令?
【发布时间】:2014-11-03 02:59:19
【问题描述】:

我想要做的是让 C 预处理器输出 #ifdef#else#endif 指令。也就是说,我想以某种方式“转义”一个指令,以便预处理器的输出包含该指令是要在输出上运行的预处理器。

是否可以“转义”一个 CPP 指令,使其由预处理器输出,如果 CPP 输出本身要进行预处理,则转义指令的输出将成为预处理器指令?

【问题讨论】:

  • @sidyll 如果 OP 两次通过预处理器运行它会这样。
  • @sidyll:是的。我正在考虑使用预处理器生成项目模板。
  • @sidyll: "...如果 CPP 输出本身要进行预处理"
  • 我怀疑有更好的工具可以满足您的想法,例如使用通用宏处理器或用方便的语言编写预处理脚本。
  • 相关(几乎是骗子):cpp: delay #include's until second pass

标签: c++ c escaping c-preprocessor


【解决方案1】:

Marcelo Cantos's answer 的一个轻微变体适用于我在 GNU cpp 4.4.3 上:

#define HASH(x) x

...

HASH(#)ifdef __cplusplus
class foo { };
HASH(#)endif

【讨论】:

  • +1。唯一的(小)故障是它将# 缩进一个空格。我相信一些旧的预处理器不喜欢这样,所以约定是缩进命令(ifdef/endif/include...),而不是#。无论如何,答案是正确的,而且很有创意。
  • @MarceloCantos:是的,我不知道那个空间是从哪里来的。 (这不是很明显:即使#define HASH(x)x 也会出现空格。)
  • 我猜这个空间与宏替换避免某些可能被解释为令牌粘贴的事情的方式有关。所以它不想在没有前面空格的情况下发出#,因为# 最终可能会附加到前面的令牌上。不过不确定。
  • @Marcelo:我们还需要担心那些 C89 之前的标准编译器吗?我从来没有遵循过这个约定,它也从来没有打动过我,但是我在 2002 年左右开始编写 C,而且我从来没有在真正过时的系统上工作过,除非你算上 Symbian/C++。写第一版 K&R 的想法有点吓人,我什至从来没有副本...
  • @SteveJessop:我同意。我只是想提一下,因为我不确定哪些编译器会受到影响。
【解决方案2】:

编辑:以下答案似乎仅适用于 cpp 的早期版本。它在 4.2.1 和 4.3.2 之间的某个地方中断。 gcc -Eg++ -E 更早打破。详情见 cmets。


这是一个似乎有效的技巧:

#define HASH() #

...

HASH()ifdef __cplusplus
class foo { };
HASH()endif

您必须直接使用cpp,因为编译器会尝试立即使用预处理器输出并且不知道如何处理未处理的指令。

【讨论】:

  • 我收到 GCC 的预处理器错误:“错误:'#' 后面没有宏参数”
  • @DanielTrebbien:你是如何调用它的?我只是将上面的代码粘贴到一个文本文件中并运行cpp file.c。它吐出了一个由#ifdef ... #endif包围的类定义。
  • ...啊,我明白了。您使用了g++ -E 建议。这似乎失败了,原因我目前无法理解。也许cpp 更宽容。
  • 我使用cpp 也失败了。 cpp --version 打印 cpp (Debian 4.3.2-1.1) 4.3.2,以防有人好奇。编辑:在另一个带有cpp (Ubuntu 4.4.3-4ubuntu5) 4.4.3 的盒子上的结果相同。
  • 我的是 4.2.1(准确地说是i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1),但我的 g++ 也是如此。
【解决方案3】:

另一个似乎有效的技巧是:

#define EMPTY
EMPTY#ifdef

使用 GCC 的预处理器(版本 4.5.2)我得到:

#ifdef

由于某种原因,这种技术与 Ilmari Karonen's solution 存在相同的主要空间问题,但这可能不是现代符合标准的 C 预处理器的问题。

【讨论】:

    猜你喜欢
    • 2021-06-30
    • 1970-01-01
    • 2018-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多