gpt4 book ai didi

c - 如何消除一个多余的宏参数

转载 作者:太空狗 更新时间:2023-10-29 17:26:18 26 4
gpt4 key购买 nike

前段时间写了一组X-macros对于一个大项目。我需要维护字符串和枚举引用/哈希值/回调函数等的连贯列表。这是函数回调的样子

#define LREF_LOOKUP_TABLE_TEXT_SIZE 32
#define _LREF_ENUM_LIST(_prefix,_ref,...) _prefix ## _ ## _ref,
#define _LREF_BASE_STRUCT_ENTRY(_prefix,_ref) .text= #_ref "\0", .position= _LREF_ENUM_LIST(_prefix, _ref)
#define _LREF_FUNCTION_STRUCT_LIST(_prefix,_ref,...) {_LREF_BASE_STRUCT_ENTRY(_prefix,_ref) _prefix ## _ ## _ref ## _callback},

#define _LREF_ENUM_TYPEDEF(_prefix) \
typedef enum _prefix \
{ \
_ ## _prefix ## s(_prefix,_LREF_ENUM_LIST) \
_LREF_ENUM_LIST(_prefix,tblEnd) \
} e_ ## _prefix

#define _LREF_LOOKUP_TABLE_TYPEDEF(_prefix, _extras) \
typedef struct _prefix ## _lookup \
{ \
const char text[LREF_LOOKUP_TABLE_TEXT_SIZE]; \
e_ ## _prefix position; \
_extras \
} _prefix ##_lookup_t

#define LREF_GENERIC_LOOKUP_TABLE(_prefix, _type, _tabledef, _listdef, _extras) \
_LREF_ENUM_TYPEDEF(_prefix); \
_LREF_LOOKUP_TABLE_TYPEDEF(_prefix,_tabledef); \
_extras \
_LREF_LOOKUP_TABLE_DECLARATION(_prefix,_listdef, _type)

#define LREF_FUNCTION_LOOKUP_TABLE(_prefix, _type) \
_ ## _prefix ## s(_prefix, _LREF_FUNCTION_DEF ) \
LREF_GENERIC_LOOKUP_TABLE( _prefix, \
_type, \
void* (*function) (void*);, \
_LREF_FUNCTION_STRUCT_LIST, )

这位于头文件中,允许我编写如下内容:

#define _cl_tags(x,_)         \
_(x, command_list) \
_(x, command) \
_(x, parameter) \
_(x, fixed_parameter) \
_(x, parameter_group) \
_(x, group) \
_(x, map) \
_(x, transform)

LREF_FUNCTION_LOOKUP_TABLE(cl_tag, static);

这使处理例程变短。例如,加载带有上述标签的配置文件很简单:

for (node_tag = cl_tag_lookup_table; node_tag->position != cl_tag_tblEnd; node_tag++)
{
if (strcasecmp(test_string, node_tag->text) == 0)
{
func_return = node_tag->function((void*)m_parser);
}
}

我的问题是:我讨厌必须在我的 #define 中包含第二个参数。我希望能够编写 #define _cl_tags(_) 而不是 #define _cl_tags(x,_)。如您所见,x 仅用于向下传递前缀 (cl_tag)。但这是多余的,因为前缀是初始宏的参数。

如果我的预处理器首先扩展最外层的宏,那么解决这个问题会很容易。不幸的是,GCC 的预处理器在扩展最外层的宏之前处理最内层的宏,即参数值。

我正在使用 gcc 4.4.5


澄清按照C89(和C99)标准,定义如下

#define plus(x,y) add(y,x)
#define add(x,y) ((x)+(y))

调用

plus(plus(a,b),c)

应该屈服

  1. plus(plus(a,b),c)
  2. 添加(c,plus(a,b))
  3. ((c)+(plus(a,b))
  4. ((c)+(add(b,a))
  5. ((c)+(((b)+(a))))

gcc 4.4.5 给出

  1. plus(plus(a,b),c)
  2. plus(add(b,a),c)
  3. plus(((b)+(a)),c)
  4. 添加(c,((b)+(a)))
  5. ((c)+(((b)+(a))))

最佳答案

这是我会做的(做过类似的):

将这些放在实用程序头文件中:

/*
* Concatenate preprocessor tokens A and B without expanding macro definitions
* (however, if invoked from a macro, macro arguments are expanded).
*/
#define PPCAT_NX(A, B) A ## B

/*
* Concatenate preprocessor tokens A and B after macro-expanding them.
*/
#define PPCAT(A, B) PPCAT_NX(A, B)

然后在包含 LREF 宏头文件之前定义它:

#define LREF_TAG cl_tag

然后,在你的 LREF 宏头文件中,

#define LREF_PFX(x) PPCAT(LREF_TAG, x)
#define LREF_SFX(x) PPCAT(x, LREF_TAG)

然后将 _prefix ## foo 的每个实例替换为 LREF_PFX(foo) 并将 foo ## _prefix 的每个实例替换为 LREF_SFX(foo )

(将两个以上的标记粘贴在一起时,只需使用嵌套的 PPCAT。)

你的调用将变成

#define LREF_TAG cl_tag
#define _cl_tags(_) \
_(command_list) \
_(command) \
_(parameter) \
_(fixed_parameter) \
_(parameter_group) \
_(group) \
_(map) \
_(transform)

LREF_FUNCTION_LOOKUP_TABLE(static);

关于c - 如何消除一个多余的宏参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5066813/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com