我认为,关键是要“排除”这种情况。例如,COND1
(或 COND2 等)应该围绕funcs
数组的定义,反之亦然。在这里,我假设您可以将条件归结为整数定义。这可以通过例如
#if COND1
# define N 1
#elif COND2
# define N 2
// ...
#endif
我们还假设您有几个函数存根(不仅是func
),它们都扩展为stub<n>
类似名称。然后您可以完全参数化您的函数名称生成,如下所示。(代码使用字符串文字连接和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;
}
文件 funcs.c 实际上定义了函数。
// Define functions named as in the struct array
// for proof of concept
#include <stdio.h>
// two-stage expansion again
#define X_LITERAL_PARAMS(f, n) \
int f ## n (void){ return printf("This is %s\n", #f #n);}
#define X(a,b) X_LITERAL_PARAMS(a,b)
#define N 1
#include "xmacro_x.h"
最后,相当无趣的文件 xmacro_x.h 提供了扩展为源文件中不同代码片段的“X 宏”。这里介绍了各种“函数族”,名称存根,稍后将与数字后缀组合。
// The "X macros" which will be expanded to different things later
X(func, N)
X(gunc, N)
//...