定义C函数数组

时间:2013-09-13 19:22:29

标签: c arrays function definition

我有一堆C函数被分配给一个函数指针数组,按照以下几行:

typedef int (*func)(int);

int SomeLongName1(int a) {         
  // ...
}                      

// ...

int SomeLongName1000(int a) {         
  // ...
}                      

func f[] = { SomeLongName1, ... , SomeLongName1000 };

这是很多工作要创建并且容易出错。例如,函数名中可能存在拼写错误,使得有效函数仍然被命名,但错误的函数仍然存在。或者,如果最后添加了一个新函数,则可能会忘记进入并将其显式添加到函数指针列表中。

为了避免必须显式声明函数指针数组,我尝试了各种技巧,例如宏,这使得代码难以理解,并且需要知道宏如何工作,而且我通常对它们不满意。

我想做的是这样的事情:

typedef int (*func)(int);

func f[] = {             
  int SomeLongName1(int a) {         
    // ...
  }                      
  // ...                   
  int SomeLongName1000(int a) {         
    // ...
  }                      
};                       

这样,数组会自动创建,如果有一些方法可以在末尾放置一个空指针,那么我可以确定有多少函数指针也很好。

然而,上面的内容并不是有效的C,而且我会以任何方式完成此任务。如果它是编译器特定的(例如GCC扩展),那就没问题。

所有函数在编译时都是静态知道的,所以我想避免必须对函数指针数组进行任何运行时初始化 - 而不是我找到了一种方法来这样做。

这个相关的问题How to define an array of functions,似乎提出了同样的问题,但并未将其纳入其逻辑结论。具体来说,我不想重新键入我已输入的任何内容,以节省时间并避免错误。

4 个答案:

答案 0 :(得分:4)

如果您不关心数组中函数的顺序,并且愿意使用GCC扩展,那么您可以使用一大堆初始化器(构造函数)函数来实现您想要的功能。这显然不是理想的,因为定义了额外的功能,但它肯定是你可以考虑的一种方法。它在运行时构造数组。

定义函数append以将单个函数附加到数组(如果需要,可以重新分配)。然后,代码基本上是

#define ARRAYFUNC(name) int name(int); \
    void __attribute__((constructor)) __init_##name(void) { append(func); } \
    int name(int a)

ARRAYFUNC(func1) {
    ...
}

ARRAYFUNC(func2) {
    ...
}

答案 1 :(得分:3)

您可以使用C预处理器(X-Macros):

#include <stdio.h>

// define a list of function names and bodies
#define FUNCS \
  FUNC(add, { return a+b; }) \
  FUNC(mul, { return a*b; }) \
  FUNC(div, { return a/b; })

// let the preprocessor make up the actual function implementations
#define FUNC(name, body) int name(int a, int b) body
FUNCS
#undef FUNC

typedef int (*func)(int, int);

// let the preprocessor populate the array of function pointers
func f[] = {
#define FUNC(name, body) name, 
FUNCS
#undef FUNC
};

// use it:
int main () {
    int a = 2, b = 3, i = 0;
    for (; i < sizeof(f)/sizeof(*f); i++) {
        printf("%d\n", f[i](a,b));
    }
    return 0;
}

输出结果为:

$ gcc test.c && ./a.out
5
6
0

答案 2 :(得分:2)

我认为没有其他办法可以做你想做的事。

你写的是什么

func f[] = { SomeLongName1, ... , SomeLongName1000 };

已经做了最好的事情。

也许你可以用前缀0000到1000来命名你的函数,这样你就可以确保每个函数都在函数指针数组中的正确位置。

另外,如果你真的有1000种不同的功能,它们肯定是共同的东西,可以引导你在几个数组中对它们进行排序,减少编号工作量,并且不易出错。

答案 3 :(得分:2)

我将用什么来解决这种情况(当然,当我无法避免它时),就是使用预处理。不是C预处理器提供的那个,它不提供合理语法所需的功能,而是一个非常强大的语法,如m4

使用m4,您的代码可能如下所示:

define(`functionList', `, 0')
define(`functionArrayMember', `define(`functionList', `$1, 'FunctionList)$1')
define(`buildFunctionArray', `{ functionList }')

int functionArrayMember(SomeLongName1)(int a) {
    return a+1;
}
//...
int functionArrayMember(SomeLongName1000)(int a) {
    return a+1;
}

func f[] = buildFunctionArray();

您只需要为m4functionArrayMember()提供正确的buildFunctionArray()定义,并且您拥有所需的功能。