宏依赖宏

时间:2011-02-07 23:35:15

标签: c gcc macros c-preprocessor

是否可以做这样的事情:

  #define F(x) \
    #ifdef DOUBLE \
      2*x \
    #else \
      x \
    #endif

这样当我使用F时,它扩展到什么取决于是否定义了宏DOUBLE?我不这么认为,但我很有希望。 GNU扩展很好。

修改 为了回答一些答案,我实际上是用它来做一些代码生成,代码稍有不同,具体取决于它的定义位置。由于包含某些文件的顺序以及需要定义相关宏的位置,以此方式切换它需要一些因子。我可能不得不这样做,但如果我不必从这个角落重新点燃自己,我会很激动!

4 个答案:

答案 0 :(得分:13)

有什么问题
#ifdef DOUBLE
  #define F(x) (2 * (x))
#else
  #define F(x) (x)
#endif

答案 1 :(得分:8)

如果我们可以限制问题,你可以做到这一点。具体来说,如果您可以保证DOUBLE

  • 未定义为宏,或
  • 被定义为扩展为空令牌序列的宏(例如#define DOUBLE),

然后你可以使用带有标记连接的间接方法:

#define F_IMPL_(x)       DOUBLE_IS_DEFINED
#define F_IMPL_DOUBLE(x) DOUBLE_NOT_DEFINED

#define F_1(x, m) F_2(x, m)
#define F_2(x, m) F_IMPL_ ## m ( x )

#define F(x) F_1(x, DOUBLE)

用法示例:

F(t)
#define DOUBLE
F(t)

预处理后的结果:

DOUBLE_NOT_DEFINED
DOUBLE_IS_DEFINED

如果DOUBLE(如果已定义)被定义为扩展为单个已知令牌的宏,如果该令牌可以构成标识符的一部分(例如,TRUE1)。要处理此问题,您只需将F_IMPL_宏重命名为F_IMPL_{TOKEN}(例如F_IMPL_TRUEF_IMPL_1)。

答案 2 :(得分:4)

为什么不以相反的方式进行嵌套?

#ifdef DOUBLE
#define F(x) (2*(x))
#else
#define F(x) (x)
#endif 

答案 3 :(得分:3)

没有。您可以做的最接近的事情是将其放在头文件中,并在每次您关心的定义发生变化时#include该头文件。这有时称为“X”模式,因为X用作更改定义的宏。

例如,该模式的一个常见用法是自动生成枚举值的字符串名称:

// File myenum_values.h
// NOTE: _no_ header guards so we can include this file multiple times
X(Apple)
X(Orange)
X(banana)

// File myenum.h
enum Fruit
{
#define X(x) x,
#include "myenum_values.h"
}

const char *FruitNames[] =
{
#undef X
#define X(x) #x,
#include "myenum_values.h"
};

// We now have an array of fruit names without having to define the enum twice