你能嵌套C预处理器指令吗?

时间:2009-01-09 06:14:22

标签: metaprogramming c-preprocessor preprocessor-directive

例如,以下是可能的:

#define definer(x) #define #x?

6 个答案:

答案 0 :(得分:9)

不,你做不到。
在定义中,磅(#)符号具有不同的含义。这意味着 - 如果这是一个参数,请通过引用它使其成为一个字符串。

答案 1 :(得分:8)

您无法嵌套C预处理程序指令。幸运的是,几乎没有必要。 如果你真的需要那种力量,你几乎肯定会更好地与另一种力量相提并论 在将代码交给C编译器之前运行的预处理器。例如:

sed 's/@CUSTOMER@/J. Random Person/' foo.c.in > foo.c
cc foo.c

另一个有用的技巧是将技巧分离为单个头文件,即 由您自己编写的程序生成:

./generate-trickery --greet 'J. Random Person' > foo.h

其中foo.h看起来像这样:

#define GREET(x) ("J. Random Person greets you, " #x)

如果你将它与Makefile或其他一些自动化结合在一起,那就是 非常无缝,不会让你的发展更加快乐。

答案 2 :(得分:3)

不,你做不到。

您可以从另一个宏引用一个宏,但不能从另一个宏定义一个宏。

答案 3 :(得分:3)

如果您正在尝试创建一段可以多次调用以执行稍微不同的事情的预处理器代码段,那么您可以执行此操作的一种方法是将代码隔离到单个.h文件中你然后多次#include。我们的想法是,每当你#include文件“调用你的例行程序”时 - 你通过#define首先.h包含文件所引用的某些预处理器常量来“传递参数”。

我认为这有用的一个地方是生成“智能”枚举,这些枚举可以转换为/从其“字符串化”形式(这对I / O非常有用)。您创建一个包含例如的ENUMVAL(foo) ENUMVAL(bar) ENUMVAL(baz) 文件。

#include

然后稍后ENUMVAL()这个文件两次:一次定义enum以创建ENUMVAL()声明,一次定义{{1}}时这样一种生成字符串化名称数组的方法。通过这种方式,您不需要多次指定实际令牌列表。

答案 4 :(得分:2)

#define definer(x) #define #x?

#x是x的字符串化。你不能#define一个字符串标记。 (#define“foo”。)它必须是标识符 [a-zA-Z0-9 _] * 标记。

不能嵌套#define那样。 #define中不能有#define。

可以在#if块内有#if。

#ifdef FOO

#ifdef BAR
 ...
#else // BAR
 ...
#endif // BAR

#else // FOO
 ...
#endif //FOO

您在#if宏中可以使用的表达式也有些限制。但你有时可以解决这个问题。例如:

        /* Use CONCATENATE_4_AGAIN to expand the arguments to CONCATENATE_4 */
#define CONCATENATE_4(      a,b,c,d)  CONCATENATE_4_AGAIN(a,b,c,d)
#define CONCATENATE_4_AGAIN(a,b,c,d)  a ## b ## c ## d

    /* Creates a typedef that's legal/illegal depending on EXPRESSION.       *
     * Note that IDENTIFIER_TEXT is limited to "[a-zA-Z0-9_]*".              *
     * (This may be replaced by static_assert() in future revisions of C++.) */
#define STATIC_ASSERT( EXPRESSION, IDENTIFIER_TEXT)                     \
  typedef char CONCATENATE_4( static_assert____,      IDENTIFIER_TEXT,  \
                              ____failed_at_line____, __LINE__ )        \
            [ (EXPRESSION) ? 1 : -1 ]

加上类似的东西:

STATIC_ASSERT( sizeof(int1) == 1, sizeof_int1_equal_1 );

(是的,我知道 #include< stdint.h> 。这只是一个例子。)

答案 5 :(得分:0)

虽然您的语法无效,但问题的答案在技术上是肯定的。但它只能通过令你的代码难以理解且无法维护的令人讨厌的技巧来实现。

另请参阅:http://www.ioccc.org/years.html#1995_vanschnitzhttp://www.ioccc.org/years.html#2004_vik2