【问题标题】:macro dependent macro宏依赖宏
【发布时间】:2011-02-07 23:35:15
【问题描述】:
是否可以这样做:
#define F(x) \
#ifdef DOUBLE \
2*x \
#else \
x \
#endif
所以当我使用F 时,它扩展到什么取决于是否定义了宏DOUBLE?我不这么认为,但我充满希望。 GNU 扩展很好。
编辑
作为对一些答案的回应,我真的在使用它来进行一些代码生成,其中代码根据定义的位置而略有不同。由于包含某些文件的顺序以及需要定义相关宏的位置,因此以这种方式切换它需要一些因素。我可能不得不这样做,但如果我不必从这个角落把自己画下来,我会很高兴!
【问题讨论】:
标签:
c
gcc
macros
c-preprocessor
【解决方案1】:
怎么了
#ifdef DOUBLE
#define F(x) (2 * (x))
#else
#define F(x) (x)
#endif
【解决方案2】:
如果我们可以约束问题,您就可以做到这一点。具体来说,如果您可以保证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(如果已定义)被定义为扩展为单个已知标记的宏,并且该标记可以构成标识符的一部分(例如,TRUE 或 1 )。要处理此问题,您只需将 F_IMPL_ 宏重命名为 F_IMPL_{TOKEN}(例如,F_IMPL_TRUE 或 F_IMPL_1)。
【解决方案3】:
为什么不反过来嵌套呢?
#ifdef DOUBLE
#define F(x) (2*(x))
#else
#define F(x) (x)
#endif
【解决方案4】:
没有。您可以做的最接近的事情是将其放入头文件中,并在每次您关心的定义更改时#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