例如,以下是否可能:
#define definer(x) #define #x?
不,你不能那样做。
磅 ( #
) 符号在定义中具有不同的含义。这意味着 - 如果这是一个参数,则通过引用它使其成为一个字符串。
您不能嵌套 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 或其他一些自动化结合在一起,它将非常无缝,不会过多地妨碍您的开发。
不,你不能那样做。
您可以从另一个宏引用一个宏,但不能从另一个宏定义一个宏。
如果您正在尝试创建一段可以多次调用以执行略有不同的事情的预处理器代码,那么您可以执行此操作的一种(适度糟糕的)方法是将代码隔离到一个.h
文件中,然后再执行#include
几次。这个想法是,每次你#include
“调用你的例程”文件时——你“传递参数”首先#define
是包含文件引用的某些预处理器常量。
我看到这很有用的一个地方是生成“智能”枚举,这些枚举可以转换为/从它们的“字符串化”形式转换(这对 I/O 很有用)。您创建一个.h
包含例如的文件
ENUMVAL(foo)
ENUMVAL(bar)
ENUMVAL(baz)
然后是#include
这个文件两次:一次 whereENUMVAL()
以创建enum
声明的方式定义,一次 whenENUMVAL()
以生成字符串化名称数组的方式定义。通过这种方式,您无需多次指定实际令牌列表。
#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>。这只是一个例子。)
尽管您的语法无效,但您的问题的答案在技术上是肯定的。但这只能通过使您的代码不可读和不可维护的讨厌的技巧来完成。
另见: http: //www.ioccc.org/years.html#1995_vanschnitz和http://www.ioccc.org/years.html#2004_vik2