使用通用函数指针
我有一个结构数组。该结构有两个函数指针。数组的每个元素都需要函数指针指向不同的函数,这样就可以在不知道具体函数名的情况下调用特定元素对应的函数。作为函数指针的新手,在我看来,我所做的事情是行不通的,但我不确定如何正确地做到这一点。如何调用所指向的函数之一的示例也将受到赞赏。
以下是我尝试引用的函数的原型:
int edit_translate_concise(struct ged *gedp, const union edit_cmd * const cmd);
int edit_translate_add_arg(union edit_cmd * const cmd, struct edit_arg * const arg);
该结构体和该结构体的数组如下:
struct edit_cmd_tab {
char *name;
char *opt_global;
char *usage;
char *help;
int (*exec_concise)(struct ged *gedp, const union edit_cmd *const cmd);
int (*add_arg)(union edit_cmd *const cmd, struct edit_arg *const arg);
};
static const struct edit_cmd_tab edit_cmds[] = {
...
{"translate", (char *)NULL,
"[FROM] TO OBJECT ...",
"[[-n] -k {FROM_OBJECT | FROM_POS}]\n"
"[-n] [-a | -r] {TO_OBJECT | TO_POS} OBJECT ...",
&edit_translate_concise,
&edit_translate_add_arg
},
...
};
因此,我需要指向的函数采用相同的参数并返回与 的函数指针成员相同的类型结构。
我收到这些警告,指的是第一个结构的最后两行:
/home/bhinesley/brlcad-trunk/src/libged/edit.c:866:55: warning: ‘union edit_cmd’ declared inside parameter list [enabled by default]
/home/bhinesley/brlcad-trunk/src/libged/edit.c:866:55: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default]
/home/bhinesley/brlcad-trunk/src/libged/edit.c:867:54: warning: ‘union edit_cmd’ declared inside parameter list [enabled by default]
这些警告指的是数组的最后两行:
/home/bhinesley/brlcad-trunk/src/libged/edit.c:1188:2: warning: initialization from incompatible pointer type [enabled by default]
/home/bhinesley/brlcad-trunk/src/libged/edit.c:1188:2: warning: (near initialization for ‘edit_cmds[1].exec_concise’) [enabled by default]
/home/bhinesley/brlcad-trunk/src/libged/edit.c:1190:5: warning: initialization from incompatible pointer type [enabled by default]
/home/bhinesley/brlcad-trunk/src/libged/edit.c:1190:5: warning: (near initialization for ‘edit_cmds[1].add_arg’) [enabled by default]
I have an array of structs. The struct has two function pointers. Each element of the array needs the function pointers to point to different functions, so that the function corresponding to a particular element can be called without knowing the specific function name. Being new to function pointers, it seems to me that what I'm doing is not going to work, but I'm not sure how to do it correctly. An example of how to call one of the functions being pointed to would also be appreciated.
Here are the prototypes of the functions I'm trying to reference:
int edit_translate_concise(struct ged *gedp, const union edit_cmd * const cmd);
int edit_translate_add_arg(union edit_cmd * const cmd, struct edit_arg * const arg);
The struct and the array of that struct are as follows:
struct edit_cmd_tab {
char *name;
char *opt_global;
char *usage;
char *help;
int (*exec_concise)(struct ged *gedp, const union edit_cmd *const cmd);
int (*add_arg)(union edit_cmd *const cmd, struct edit_arg *const arg);
};
static const struct edit_cmd_tab edit_cmds[] = {
...
{"translate", (char *)NULL,
"[FROM] TO OBJECT ...",
"[[-n] -k {FROM_OBJECT | FROM_POS}]\n"
"[-n] [-a | -r] {TO_OBJECT | TO_POS} OBJECT ...",
&edit_translate_concise,
&edit_translate_add_arg
},
...
};
So, the functions I need to point to take the same arguments and return the same type as the function pointer members of the struct.
I'm getting these warnings, referring to the last two lines of the first struct:
/home/bhinesley/brlcad-trunk/src/libged/edit.c:866:55: warning: ‘union edit_cmd’ declared inside parameter list [enabled by default]
/home/bhinesley/brlcad-trunk/src/libged/edit.c:866:55: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default]
/home/bhinesley/brlcad-trunk/src/libged/edit.c:867:54: warning: ‘union edit_cmd’ declared inside parameter list [enabled by default]
And these warnings referring to the last two lines of the array:
/home/bhinesley/brlcad-trunk/src/libged/edit.c:1188:2: warning: initialization from incompatible pointer type [enabled by default]
/home/bhinesley/brlcad-trunk/src/libged/edit.c:1188:2: warning: (near initialization for ‘edit_cmds[1].exec_concise’) [enabled by default]
/home/bhinesley/brlcad-trunk/src/libged/edit.c:1190:5: warning: initialization from incompatible pointer type [enabled by default]
/home/bhinesley/brlcad-trunk/src/libged/edit.c:1190:5: warning: (near initialization for ‘edit_cmds[1].add_arg’) [enabled by default]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你[几乎]做的每件事都是正确的。
但是,您必须确保在函数原型中使用实际的 union
union edit_cmd
之前已对其进行了声明。如果您忘记声明它,编译器会将union edit_cmd
视为全新联合类型的声明,该类型对于函数原型来说是本地。即,union edit_cmd
的本地声明与您在其他地方拥有的union edit_cmd
的实际声明没有关系。这就是你的情况发生的情况。这就是编译器试图警告您的内容。这同样适用于
struct ged
和struct edit_arg
。显然,您忘记包含包含union edit_cmd
、struct ged
和struct edit_arg
声明的头文件。例如,这段简单的代码说明了
foo
原型中声明的union bar
与后面声明的union bar
完全没有关系的问题。前者是原型的本地,后者是全局(即文件级类型)。如果您稍后尝试这样做,您将从编译器收到有关参数类型不匹配的诊断消息。同样的不匹配是导致帖子中第二组警告的原因(关于数组初始化中不兼容的指针类型)。
但是,如果您以这种方式重新排列声明,
一切都会正常工作,因为原型中的
union bar
现在引用了之前声明的union bar
。或者,您可以前向声明union bar
,如下所示。这也将使编译器将
foo
中的union bar
视为全局< /em> 类型(即文件级类型),而不是本地类型。至于通过指针调用函数,可以使用 * 运算符
,甚至可以不用
*
运算符来完成。 总结以上内容,解决您所观察到的问题的简单方法是添加文件级前向在函数原型之前声明 struct 和 union 类型
更优雅的方法是在原型声明之前包含这些类型的完整定义。
You are doing [almost] everything correctly.
However, you have to make sure that the actual union
union edit_cmd
is declared before you use it in function prototype. If you forget to declare it, the compiler will treatunion edit_cmd
as a declaration of a completely new union type, which is local to function prototype. I.e. this local declaration ofunion edit_cmd
will have no relation to the actual declaration of yourunion edit_cmd
you'll have elsewhere.This is what happens in your case. This is what the compiler is trying to warn you about. The same applies to
struct ged
and tostruct edit_arg
. Apparently, you forgot to include the header files that contain declarations ofunion edit_cmd
,struct ged
andstruct edit_arg
.For example, this simple code illustrates the problem
the
union bar
declared in thefoo
's prototype has absolutely no relation tounion bar
declared later. The former is local to the prototype, the latter is global (i.e. file-level type). If you later try to doyou'll get a diagnostic message from the compiler about argument-parameter type mismatch. The very same mismatch is what causing the second group of warnings in your post (about incompatible pointer types in array initialization).
But if you rearrange the declarations in this way
everything will work fine, since
union bar
in the prototype now refers to previously declaredunion bar
. Alternatively, you can forward-declareunion bar
as inThis will also make the compiler treat
union bar
infoo
as a global type (i.e. file-level type), not as a local one.As for calling your functions through the pointers, it can be done as either
or even without the
*
operatorTo summarize the above, the easy fix to the problems you are observing is to add the file-level forward declarations for the
struct
andunion
type before the function prototypesA more elegant approach would be to include the full definitions of these types before the prototype declarations.