使用泛型函数指针

时间:2011-07-27 23:28:33

标签: c arrays struct function-pointers abstraction

我有一系列结构。该struct有两个函数指针。数组的每个元素都需要函数指针指向不同的函数,以便可以在不知道特定函数名的情况下调用对应于特定元素的函数。作为函数指针的新手,在我看来,我正在做的事情不会起作用,但我不确定如何正确地做到这一点。如何调用所指向的函数之一的示例也将受到赞赏。

以下是我试图引用的函数的原型:

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]

1 个答案:

答案 0 :(得分:8)

你正在做几乎所有事情。

但是,在函数原型中使用它之前,必须确保声明实际的union union edit_cmd。如果您忘记声明它,编译器会将union edit_cmd视为一个全新的联合类型的声明,它是 local 到函数原型。即union edit_cmd本地声明与您在其他地方union edit_cmd的实际声明无关。

这就是你的情况。这就是编译器试图警告你的内容。这同样适用于struct gedstruct edit_arg。显然,您忘记包含包含union edit_cmdstruct gedstruct edit_arg声明的标头文件。

例如,这个简单的代码说明了问题

void foo(union bar *p);

union bar {
  int a;
};

union bar原型中声明的foo与稍后声明的union bar完全没有关系。前者是原型的 local ,后者是 global (即文件级类型)。如果你以后尝试做

union bar u;
foo(&u);

您将从编译器获得有关参数参数类型不匹配的诊断消息。同样的不匹配是导致帖子中第二组警告的原因(关于数组初始化中不兼容的指针类型)。

但是如果你以这种方式重新安排声明

union bar {
  int a;
};

void foo(union bar *p);

一切都会正常工作,因为原型中的union bar现在引用先前声明的union bar。或者,您可以在

中转发声明union bar
union bar;
void foo(union bar *p);

union bar {
  int a;
};

这也将使编译器将union bar中的foo视为全局类型(即文件级类型),而不是本地类型。

至于通过指针调用函数,它可以作为

完成
(*edit_cmds[i].add_arg)( /* arguments go here */ );

甚至没有*运算符

edit_cmds[i].add_arg( /* arguments go here */ );

总结以上内容,您正在观察的问题的简单修复是在函数原型之前添加structunion类型的文件级前向声明

struct ged;
union edit_cmd;
struct edit_arg;
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);

更优雅的方法是在原型声明之前包含这些类型的完整定义。