C“#define”函数名称生成

时间:2014-08-15 00:20:46

标签: c c-preprocessor

我有concrete_impl.h(按原样):

#ifdef TUPLE_ITERATOR_WITH_INDEX
    #define TUPLE_ITERATOR TUPLE_ITERATOR_NO_INDEX
    #define iterate_tuple_fname iterate_tuple_id
#else
    #define TUPLE_ITERATOR TUPLE_ITERATOR_INDEX
    #define iterate_tuple_fname iterate_tuple
#endif

#undef  iterate_tuple_fname_back
#define iterate_tuple_fname_back iterate_tuple_fname##_back

static void iterate_tuple_fname()         // ok 
{
}

static void iterate_tuple_fname_back()   // redefinition error
{
}

concrete.h(原样):

#ifndef CONCRETE_H
#define CONCRETE_H

#define TUPLE_ITERATOR_WITH_INDEX
#include "concrete_impl.h"

#undef TUPLE_ITERATOR_WITH_INDEX
#include "concrete_impl.h"


#endif // CONCRETE_H

我想得到的是4个功能:

  • iterate_tuple
  • iterate_tuple_id
  • iterate_tuple_back
  • iterate_tuple_id_back

但是" _back"函数我有重新定义错误。为什么呢?

2 个答案:

答案 0 :(得分:1)

iterate_tuple_fname##_back只不过是iterate_tuple_fname_back。要将iterate_tuple_fname替换为其宏替换列表,您需要一个辅助宏:

#define CONCAT(a, b) a ## b
#define iterate_tuple_fname_back CONCAT(iterate_tuple_fname, _back)

更新:对不起,经过几年的C#编程,已经忘记了所有关于C的事。

实际上需要 double 运行辅助宏:

#define CONCAT1(a, b) a ## b
#define CONCAT(a, b) CONCAT1(a, b)
#define iterate_tuple_fname_back CONCAT(iterate_tuple_fname, _back)

答案 1 :(得分:0)

显然你误解了##运算符的工作原理。

  • 如果与##运算符相邻的预处理标记是当前宏的参数,则递归分析此参数以进一步替换 first ,并将替换结果替换为结果。

  • 如果与##运算符相邻的预处理标记不是当前宏的参数,则不会进行递归分析和替换该标记。令牌简单地与另一个令牌连接。

稍后,一旦替换了所有参数并连接了所有连接,将再次重新扫描整个结果以进行进一步替换。但是你的例子已经为时已晚。

在您的情况下,您定义了此宏

#define iterate_tuple_fname_back iterate_tuple_fname##_back

由于iterate_tuple_fname不是此宏的参数,因此iterate_tuple_fname不会进行早期替换。整个事情立即连接到iterate_tuple_fname_back,然后才重新扫描。但重新扫描发现没有什么可以替代,所以iterate_tuple_fname_back是最终的结果。

如果您希望预处理器替换##运算符的左侧(显然是您的意图),则必须在左侧使用宏参数,如

#define ITF_back(prefix) prefix##_back

然后您可以将此宏用作

ITF_back(iterate_tuple_fname)

现在iterate_tuple_fname内的重新扫描和递归替换将在与_back部分串联之前提前发生。即它会像你想要的那样工作。