在 C 中返回函数数组
Returning array of functions in C
我正在构建一个包含大量使用相同 "main" 功能的文件的应用程序
例如:
file1 as 3 functions called: doX, doY, doZ
file2 as 1 函数调用:abc
file3 作为 10 个函数调用:a1、a2、a3 等...
我有一个处理这些函数的主程序,以便生成和计算正确的数据。
我遇到的问题是 "main" 程序不知道要 运行 哪些函数,所以我想为我的所有文件创建一个通用函数,它将 return 列表按特定顺序
运行 的函数
但由于某些原因它不起作用
这是我的示例代码
// 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])();
^
我该如何解决这个问题?
正确的做法是
typedef int (*FunctionType)(void);
然后将函数指针声明为
FunctionType functionPointer;
你还有更多问题
- 不要 return 指向局部变量的指针。
你在 task[id] = ...
之前增加了 id
,这也是你用一种非常混乱的风格做的,有两个问题
可以使用前置自增运算符,比如
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;
}
我想,通过写作
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
作为函数指针非常方便且可读性更好。
一个函数 return 指向一个函数的指针看起来像:
int(*)()function()
而不是
int* function()
如您的代码所示。或者,您可以使用 typedef:
typedef int(*functype)();
functype function();
这让事情变得不那么混乱了。
不过,您不能 return 指向堆栈变量的指针;到您 return 时,该指针将指向无效内存。你必须使用 malloc() 或类似的东西(然后记住不要忘记清理)。或者,不要 return 指针,而是 return 结构:
struct fptrs_struct {
int(*open)();
int(*close)();
// ...
}
struct fptrs_struct function() {
struct fptrs_struct retval;
retval.open = foo;
retval.close = bar;
// ...
return retval;
}
这行得通,不需要 malloc 或类似的东西(但在 return 上涉及稍微多一点的复制)。
恭喜,您现在正在使用 C 语言进行 OO。也许为此使用一个库(提示:gobject),或者更好的是,切换到一种实际支持面向对象的语言——比如 Objective-C 或 C++.
我正在构建一个包含大量使用相同 "main" 功能的文件的应用程序
例如:
file1 as 3 functions called: doX, doY, doZ file2 as 1 函数调用:abc file3 作为 10 个函数调用:a1、a2、a3 等...
我有一个处理这些函数的主程序,以便生成和计算正确的数据。
我遇到的问题是 "main" 程序不知道要 运行 哪些函数,所以我想为我的所有文件创建一个通用函数,它将 return 列表按特定顺序
运行 的函数但由于某些原因它不起作用
这是我的示例代码
// 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])();
^
我该如何解决这个问题?
正确的做法是
typedef int (*FunctionType)(void);
然后将函数指针声明为
FunctionType functionPointer;
你还有更多问题
- 不要 return 指向局部变量的指针。
你在
task[id] = ...
之前增加了id
,这也是你用一种非常混乱的风格做的,有两个问题可以使用前置自增运算符,比如
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;
}
我想,通过写作
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
作为函数指针非常方便且可读性更好。
一个函数 return 指向一个函数的指针看起来像:
int(*)()function()
而不是
int* function()
如您的代码所示。或者,您可以使用 typedef:
typedef int(*functype)();
functype function();
这让事情变得不那么混乱了。
不过,您不能 return 指向堆栈变量的指针;到您 return 时,该指针将指向无效内存。你必须使用 malloc() 或类似的东西(然后记住不要忘记清理)。或者,不要 return 指针,而是 return 结构:
struct fptrs_struct {
int(*open)();
int(*close)();
// ...
}
struct fptrs_struct function() {
struct fptrs_struct retval;
retval.open = foo;
retval.close = bar;
// ...
return retval;
}
这行得通,不需要 malloc 或类似的东西(但在 return 上涉及稍微多一点的复制)。
恭喜,您现在正在使用 C 语言进行 OO。也许为此使用一个库(提示:gobject),或者更好的是,切换到一种实际支持面向对象的语言——比如 Objective-C 或 C++.