有没有一种方法可以逃避C预处理指令?

9
我想做的是让C预处理器输出#ifdef#else#endif指令。也就是说,我想以某种方式“转义”指令,使得预处理器的输出包含指令,如果预处理器在此输出上运行,则会生成预处理器指令。
是否可能“转义”CPP指令,以便它被预处理器输出,从而如果CPP输出本身被预处理,则转义后的指令的输出将是预处理器指令?

1
如果OP通过预处理器运行两次,它就会起作用。 - Mark B
@sidyll:没错。我在考虑使用预处理器来生成项目模板。 - Daniel Trebbien
如果 CPP 输出本身要被预处理。 - Lightness Races in Orbit
2
我怀疑你心目中有更好的工具,比如使用通用宏处理器或者编写一个方便语言的预处理脚本。 - Nicola Musatti
2
相关(几乎是重复的):cpp:延迟#include直到第二遍 - cHao
显示剩余2条评论
3个回答

11

Marcelo Cantos的答案的一个稍微不同的变体在GNU cpp 4.4.3上适用于我:

#define HASH(x) x

...

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

预处理器机制的创造性应用。 - Mark B
2
唯一(微小)的问题是它将 # 缩进了一个空格。我认为一些较早的预处理器不喜欢这样做,因此惯例是缩进命令(ifdef/endif/include...),但不缩进 #。无论如何,答案是正确的,非常有创意。 - Marcelo Cantos
1
@MarceloCantos:是啊,我也不知道那个空格从哪里来的。(显然不是因为#define HASH(x)x,即使使用这个定义仍然会出现空格。) - Ilmari Karonen
1
我猜这个空格与宏替换避免某些可能被解释为标记粘贴的东西有关。因此,它不想发出一个没有前导空格的 #,因为 # 可能会附加到前面的标记上。不过我不确定。 - Steve Jessop
1
@Marcelo:我们是否仍然需要担心那些 C89 标准之前的编译器?我从来没有遵循过那个约定,也从未遇到过问题。但是我第一次写 C 是在大约 2002 年左右,并且我从未在真正老旧的系统上工作过,除非你算上 Symbian/C++。写第一版 K&R 的想法有点可怕,我甚至都没有一本副本... - Steve Jessop
1
@SteveJessop:我同意。我只是想提一下,因为我不确定哪些编译器会受到影响。 - Marcelo Cantos

6

编辑:以下答案似乎只适用于早期版本的cpp。在4.2.1和4.3.2之间某处出现了问题。 gcc -Eg++ -E甚至更早就出现了问题。有关详细信息,请参见评论。


这里有一个看起来行得通的技巧:

#define HASH() #

...

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

由于编译器会尝试立即消耗预处理器输出并不知道如何处理未经处理的指令,因此您必须直接使用 cpp


3
我在使用GCC的预处理器时遇到了错误:“error: '#'后面没有跟着宏参数”。 - Daniel Trebbien
@DanielTrebbien: 你是怎么调用它的?我只是把上面的代码粘贴到一个文本文件中,然后运行了 cpp file.c。它将会输出被 #ifdef ... #endif 包围的类定义。 - Marcelo Cantos
啊,我明白了。你使用了g++ -E的建议。目前似乎失败了,原因我无法理解。也许使用cpp会更容易一些。 - Marcelo Cantos
1
我使用 cpp 也失败了。如果有人感兴趣,cpp --version 输出 cpp (Debian 4.3.2-1.1) 4.3.2。编辑:在另一台机器上也是相同的结果,使用的是 cpp (Ubuntu 4.4.3-4ubuntu5) 4.4.3 - Ilmari Karonen
我的版本是4.2.1(确切地说,是i686-apple-darwin11-llvm-g++-4.2(GCC)4.2.1),但我的g++也是这个版本。 - Marcelo Cantos
我刚在4.5.2(Linux)上进行了测试,结果也失败了。我想我的答案并不那么聪明(或者至少,它的聪明程度已经过期了)。 - Marcelo Cantos

5

另一个看起来可行的技巧是:

#define EMPTY
EMPTY#ifdef

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

#ifdef

由于某种原因,这种技术与Ilmari Karonen的解决方案存在相同的前导空格问题,但这可能不是现代符合标准的C预处理器的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接