结合使用C X宏和#ifdef
假设我的代码如以下代码段所示:结合使用C X宏和#ifdef,c,macros,conditional-compilation,ifdefine,C,Macros,Conditional Compilation,Ifdefine,假设我的代码如以下代码段所示: #ifdef COND1 extern int func1(void); #endif ... #ifdef CONDN extern int funcn(void); #endif my_struct funcs[] = { #ifdef COND1 {"func1 description", func1}, #endif ... #ifdef CONDN {"funcn description", funcn}, #endif
#ifdef COND1
extern int func1(void);
#endif
...
#ifdef CONDN
extern int funcn(void);
#endif
my_struct funcs[] = {
#ifdef COND1
{"func1 description", func1},
#endif
...
#ifdef CONDN
{"funcn description", funcn},
#endif
{NULL, NULL},
};
是否可以将其替换为,以尽量减少两部分中函数名称和条件的重复
如果没有#ifdef CONDX
条件,这看起来相当简单。但是,我不知道如何将它们包含在X宏中,因为不允许在\define
中使用\ifdef
不确定X宏是否是这里的解决方案。但是,您可以使用一些预处理器魔法来减少键入。在您的示例中,问题仍然是条件编译(#ifdef
s)。如果不知道这些情况是什么样子,就很难进一步减少键入的数量
进行以下操作:
#define D(n) extern int func ## n(void);
#define A(n) {"func" #n " description", func ## n},
#ifdef COND1
D(1)
#endif
#ifdef COND2
D(2)
#endif
my_struct funcs[] = {
#ifdef COND1
A(1)
#endif
#ifdef COND2
A(2)
#endif
};
#define COND1(...) __VA_ARGS__
#define CONDN(...)
#define MY_XLIST \
X(COND1, func1, "func1 description") \
X(CONDN, funcn, "funcn description")
#define X(a, b, c) a(extern int b (void);)
MY_XLIST
#undef X
#define X(a, b, c) a({c, b},)
my_struct funcs[] = {
MY_XLIST
{NULL, NULL},
};
#undef X
我认为,这是朝着你的目标迈出的一步。要了解它的作用,您可以尝试
gcc -E -DCOND1 <file-with-contents-above>.c
gcc-E-DCOND1.c
(如果您在某些Unix上)或
cl-E-DCOND1.c
(如果您在Windows上使用Visual Studio)。假设您要定义COND1,但不定义CONDN。我认为你可以做到以下几点:
#define D(n) extern int func ## n(void);
#define A(n) {"func" #n " description", func ## n},
#ifdef COND1
D(1)
#endif
#ifdef COND2
D(2)
#endif
my_struct funcs[] = {
#ifdef COND1
A(1)
#endif
#ifdef COND2
A(2)
#endif
};
#define COND1(...) __VA_ARGS__
#define CONDN(...)
#define MY_XLIST \
X(COND1, func1, "func1 description") \
X(CONDN, funcn, "funcn description")
#define X(a, b, c) a(extern int b (void);)
MY_XLIST
#undef X
#define X(a, b, c) a({c, b},)
my_struct funcs[] = {
MY_XLIST
{NULL, NULL},
};
#undef X
问题是,您需要定义所有宏,但扩展不同。您不能在\define
中使用\ifdef
,因此您不能使用基于\define
的X宏,但仍然可以使用基于\include
的X宏
例如,使用文件t.def
:
#ifdef COND1
F(func1, "func1 description")
#endif
#ifdef COND2
F(func2, "func2 description")
#endif
在主文件中:
#define COND2
#define F(name, desc) extern int name(void);
#include "t.def"
#undef F
mystruct funcs[] = {
#define F(name, desc) {desc, name},
#include "t.def"
#undef F
{NULL, NULL},
};
这将被处理为:
extern int func2(void);
mystruct funcs[] = {
{"func2 description", func2},
{NULL, NULL},
};
我认为,关键是“排除”这种情况。例如,COND1
(或COND2等)应该围绕funcs
数组的定义,反之亦然。这里我假设您可以将条件归结为整数定义。这可以通过以下方式实现:
#if COND1
# define N 1
#elif COND2
# define N 2
// ...
#endif
我们还假设您有多个函数存根(不仅是func
),它们都扩展为类似于存根的名称。然后您可以完全参数化您的函数名生成,如下所示。(代码使用字符串文字连接和for循环变量。gcc-std=c99
编译得很好。)
主文件。声明函数并定义描述结构数组
#include<stdio.h>
// example struct definition
typedef struct { const char* description; int (*f)(void); } my_struct;
// A two-stage macro expansion is necessary because
// macro parameters are taken literally when used in
// concatenation or stringification
// (cf. https://gcc.gnu.org/onlinedocs/cpp/Argument-Prescan.html)
// Expands to function declaration
#define X_LITERAL_PARAMS(fname, suffix) extern int fname ## suffix (void);
#define X(fname, suffix) X_LITERAL_PARAMS(fname, suffix) // this expands suffix e.g. to 1
// define extern int functions
#define N 1 // select which function variants
#include "xmacro_x.h"
#undef X_LITERAL_PARAMS
#define X_LITERAL_PARAMS(fname, suffix) { "Calling " #fname #suffix, fname ## suffix},
my_struct funcs[] = {
#undef N
#define N 1 // select which function variants
#include "xmacro_x.h"
// defines descriptions for functions
# include "xmacro_x.h"
};
// Print description and call each function
// in the struct array
int main(void)
{
for(int i=0; i<sizeof(funcs)/sizeof(my_struct); i++)
{
printf("%s yields %d\n\n", funcs[i].description, funcs[i].f());
}
return 0;
}
对x宏(我称之为列表宏)使用条件编译的关键是要理解预处理器指令不能包含在宏中,但列表宏可以从较小的列表中拼凑起来。然后,较小列表的输出可以是有条件的
解决方案在下面代码的开头,但为了完整起见,我添加了list宏的输出。另外,请注意,较小的列表是一个项目的列表,但也可以很容易地包含多个项目
//Inner macro parameter list.
//FUNC_(enumTag, function, description)
//Conditional sublist.
#ifdef COND1
#define COND1_FUNC_LIST \
FUNC_(FuncCOND_1, func1, “func1 description”)
#else
#define COND1_FUNC_LIST
#endif
//Conditional sublist.
#ifdef CONDN
#define CONDN_FUNC_LIST \
FUNC_(FuncCOND_N, funcn, “funcn description”)
#else
#define CONDN_FUNC_LIST
#endif
//Complete list.
#define FUNC_LIST \
COND1_FUNC_LIST \
CONDN_FUNC_LIST \
//Comment to terminate preprocessor continuation.
//The rest generates all of the code artifacts.
#define CONDN_FUNC_ENUM(enumTag, function, description) enumTag,
#define CONDN_FUNC_EXTERN(enumTag, function, description) extern int function(void);
#define CONDN_FUNC_INITIALIZER(enumTag, function, description) {function, description},
typedef int (*FuncPtr)(void);
typedef struct
{
FuncPtr function;
char * description;
} FuncStruct;
enum
{
FUNC_LIST(CONDN_FUNC_ENUM)
FuncCOUNT
};
FUNC_LIST(CONDN_FUNC_EXTERN)
FuncStruct funcs[FuncCOUNT] =
{
FUNC_LIST(CONDN_FUNC_INITIALIZER)
};
您应该能够通过“func”和“1”、“2”等标记连接来破解某些东西(假设我正确理解有“n”(比如20个)func替代项)。
//Inner macro parameter list.
//FUNC_(enumTag, function, description)
//Conditional sublist.
#ifdef COND1
#define COND1_FUNC_LIST \
FUNC_(FuncCOND_1, func1, “func1 description”)
#else
#define COND1_FUNC_LIST
#endif
//Conditional sublist.
#ifdef CONDN
#define CONDN_FUNC_LIST \
FUNC_(FuncCOND_N, funcn, “funcn description”)
#else
#define CONDN_FUNC_LIST
#endif
//Complete list.
#define FUNC_LIST \
COND1_FUNC_LIST \
CONDN_FUNC_LIST \
//Comment to terminate preprocessor continuation.
//The rest generates all of the code artifacts.
#define CONDN_FUNC_ENUM(enumTag, function, description) enumTag,
#define CONDN_FUNC_EXTERN(enumTag, function, description) extern int function(void);
#define CONDN_FUNC_INITIALIZER(enumTag, function, description) {function, description},
typedef int (*FuncPtr)(void);
typedef struct
{
FuncPtr function;
char * description;
} FuncStruct;
enum
{
FUNC_LIST(CONDN_FUNC_ENUM)
FuncCOUNT
};
FUNC_LIST(CONDN_FUNC_EXTERN)
FuncStruct funcs[FuncCOUNT] =
{
FUNC_LIST(CONDN_FUNC_INITIALIZER)
};