宏相关宏

发布于 2024-10-16 11:33:52 字数 367 浏览 3 评论 0原文

是否可以这样做:

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

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

编辑 为了回应一些答案,我确实使用它来进行一些代码生成,其中代码根据定义位置的不同而略有不同。由于某些文件的包含顺序以及需要定义相关宏的位置,因此以这种方式进行切换需要进行一些分解。我可能必须这样做,但如果我不必从这个角落把自己脱掉,我会很兴奋!

Is it possible to do something like this:

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

so that when I use F, what it expands to depends on whether the macro DOUBLE is defined? I don't think so, but I'm hopeful. GNU expansions are fine.

Edit
In response to some of the answers, I'm really using this to do some code generation, where the code is slightly different depending on where it gets defined. Because of the order in which some files are included and where the relevant macros need to be defined, switching it around that way requires a bit of factoring. I may have to do it, but would be thrilled if I don't have to unpaint myself from this corner!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

夏九 2024-10-23 11:33:52

出了什么问题

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

What's wrong with

#ifdef DOUBLE
  #define F(x) (2 * (x))
#else
  #define F(x) (x)
#endif
顾铮苏瑾 2024-10-23 11:33:52

如果我们能够限制问题,你就能实现这一点。具体来说,如果您可以保证 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 >)。

If we can constrain the problem, you can accomplish this. Specifically, if you can guarantee that DOUBLE is either

  • not defined as a macro, or
  • is defined as a macro that expands to an empty token sequence (e.g. #define DOUBLE),

then you can use an indirect approach with token concatenation:

#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)

Usage example:

F(t)
#define DOUBLE
F(t)

Result after preprocessing:

DOUBLE_NOT_DEFINED
DOUBLE_IS_DEFINED

This approach will also work if DOUBLE (if it is defined) is defined as a macro that expands to a single known token, if that token can form part of an identifier (e.g., TRUE or 1). To handle this, you just have to rename the F_IMPL_ macro to F_IMPL_{TOKEN} (e.g., F_IMPL_TRUE or F_IMPL_1).

悲欢浪云 2024-10-23 11:33:52

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

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

Why not do the nesting the other way around?

#ifdef DOUBLE
#define F(x) (2*(x))
#else
#define F(x) (x)
#endif 
血之狂魔 2024-10-23 11:33:52

不。您能做的最接近的事情就是将其放入头文件中,并在每次您关心的定义发生更改时 #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

No. The closest thing you can do is to put that in a header file, and #include that header file each time the definitions you care about change. This is sometimes called the "X" pattern, because X is used as a macro that changes definition.

For example, one common usage of that pattern is to autogenerate the string names of enum values:

// 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文