我正在构建一个包含大量使用相同“主要”功能的文件的应用
例如:
file1作为3个函数调用:doX,doY,doZ file2作为1函数调用:abc file3作为10个函数调用:a1,a2,a3等......
我有一个主程序来处理这些函数,以生成和计算正确的数据。
我遇到的问题是“主”程序不知道要运行哪些函数所以我想为我的所有文件创建一个通用函数,它将返回以特定顺序运行的函数列表
但由于某种原因它不起作用
以下是我的示例代码
// in main.h
#include <stdio.h>
// in file1.c
// #include ...
int doX() {
// do stuff
return 1;
}
int doY() {
// do stuff
return 1;
}
int * get_tasks() {
int (*task[2])() = { };
int id = 0;
id++; task[id] = doX;
id++; task[id] = doY;
return *task;
}
// main.c
#include "main.h"
int main () {
int * pl;
int i, success = 0;
printf("do stuff");
pl = get_tasks();
for(i = 0; i < 2; i++) {
success += *(pl[i])();
}
printf("success = %d", success);
}
当我跑:gcc * .c
我得到:
test.c: In function ‘get_tasks’:
test.c:24:3: warning: return from incompatible pointer type [enabled by default]
return *task;
^
test.c: In function ‘main’:
test.c:38:24: error: called object is not a function or function pointer
success += *(pl[i])();
^
我该如何解决这个问题?
答案 0 :(得分:3)
正确的做法是
typedef int (*FunctionType)(void);
然后将函数指针声明为
FunctionType functionPointer;
你还有更多问题
您在id
之前增加task[id] = ...
,这也是一个非常混乱的风格,有2个问题
您可以使用预增量运算符,例如
task[++id] = ...;
它仍然是错误的,因为数组是基于索引的0
,所以通过访问task[1]
实际上是数组的末尾,task[2]
会导致未定义行为。
这是您的代码的工作版本
#include <stdio.h>
typedef int (*FunctionType)(void);
int doX(void) {
return 1;
}
int doY(void) {
return 1;
}
void gettasks(FunctionType task[2])
{
int id = 0;
task[id++] = doX;
task[id++] = doY;
}
int main(void) {
FunctionType tasks[2];
int i, success = 0;
printf("do stuff\n");
gettasks(tasks);
for(i = 0; i < 2; i++) {
success += tasks[i]();
}
printf("success = %d", success);
return 0;
}
答案 1 :(得分:2)
返回指向函数的指针的函数如下所示:
int(*)()function()
而不是
int* function()
与您的代码一样。或者,您可以使用typedef:
typedef int(*functype)();
functype function();
这让事情变得更加混乱。
但是,您无法返回指向堆栈变量的指针;返回时,该指针将指向无效内存。你必须使用malloc()或其他一些(然后记住不要忘记清理)。或者,不要返回指针,而是返回结构:
struct fptrs_struct {
int(*open)();
int(*close)();
// ...
}
struct fptrs_struct function() {
struct fptrs_struct retval;
retval.open = foo;
retval.close = bar;
// ...
return retval;
}
这样做,并且不需要malloc或其他一些(但在返回时涉及稍微复制)。
恭喜,你现在正在C中做OO。也许使用一个库(提示:gobject),或者更好的是,切换到实际支持面向对象的语言 - 比如Objective-C或者C ++。
答案 2 :(得分:1)
我认为,通过写作
int (*task[2])() = { };
int id = 0;
id++; task[id] = doX;
id++; task[id] = doY;
您正在尝试访问索引1
和2
,这是undefined behaviour的内存溢出和原因。
之后,task[2]
是get_tasks()()
的本地人。您不应该返回相同的地址,因为get_tasks()
完成后,task[2]
不再存在。返回地址并在呼叫者中再次使用该地址会导致undefined behaviour。
也就是说,在我看来,使用typedef
作为函数指针非常方便,更具可读性。