在定义另一个宏时,我可以捕获一个宏的基础值吗?

时间:2017-02-07 17:12:00

标签: c c-preprocessor

想象一下,我希望#define一个宏,使其等于另一个宏的当前值(如果存在这样的概念)。

例如:

#include "def_a.h"  // defines macro A
#define B A

这将B定义为A。如果A稍后更改定义(即通过重新定义),则B的值也会发生变化(因为B在使用时会扩展为A,这会进一步扩展到A)的新值。

我想要的是某种方式将A的价值“加入”B,以便B只扩展为A的值,而不是A本身。

例如:

#define A first
#define B BAKE_IN(A)
#undef A
#define A second
#define C BAKE_IN(A)
#undef A
#define A third

// here I want B to expand to first, and C to expand to second

当然BAKE_IN不是真的,但我想知道是否有办法达到这个效果。

现在,我并没有真正说明如果A本身是用其他宏来定义会发生什么,但我可以用“一级扩展”(即B得到A的值扩展,所以进一步的宏仍然是“完全扩展”(即A完全展开,递归,就像在使用点一样)。

2 个答案:

答案 0 :(得分:1)

宏在#define指令的主体中永远不会被替换,所以没有办法将宏定义为另一个宏的当前值,除了宏的有限情况,其值是一个常量算术表达式

在后一种情况下,您可以使用Boost preprocessor library.中的BOOST_PP_ASSIGN_SLOT(尽管大多数Boost库都是特定于C ++的,但Boost预处理器库适用于C和C ++,并且没有依赖性在任何其他Boost组件上。)

答案 1 :(得分:1)

我认为没有一个干净的解决方案。我发现最接近的事情是在char数组中保留“字符串化”值:

#include <stdio.h>

#define BAKE_IN(X, id) BAKE_IN_REAL(X ## _, X, id)
#define BAKE_IN_REAL(X, Y, id) static const char X ## id[] = #Y;
#define BAKE_OUT(X, id) X ## _ ## id

#define A first
BAKE_IN(A, 1)
#define B BAKE_OUT(A, 1)
#undef A

#define A second
BAKE_IN(A, 2)
#define C BAKE_OUT(A, 2)
#undef A

int main(void)
{
    printf("%s\n", B); // prints "first"
    printf("%s\n", C); // prints "second"
    return 0;
}

这个想法是BAKE_IN宏声明对象命名为例如A_1,其中包含A的当前扩展。

有两个主要限制:

  • 每对BAKE_INBAKE_OUT都需要唯一ID
  • 扩展仅以“字符串化”形式提供