2

我是 C 的新手,来自 Java 背景。

如果我有一个使用来自结构定义内部函数的数据动态初始化的结构,那么这些函数什么时候被调用?这段代码什么时候运行?它只是在第一次引用时sample_struct_table[i]

static struct sample_struct {
    int         command;
    int         (*foo)( obj1 *banana, int num);
} sample_struct_table[] = {
    {   .command    =   COMMAND_1,
        .foo =   function_name,
    },
    {   .command    =   COMMAND_2,
        .foo =   another_function_name,
    },
};

static int function_name(obj1 *banana, int num)
{
      // do stuff here
      // When does this get called?
}
4

3 回答 3

6

当你调用它们时,函数会被调用。在您的示例中,您所做的只是将结构的字段设置为函数指针。该函数没有被调用,你只有一个指向它的指针。

于 2012-12-10T23:31:29.657 回答
3

简短的回答:当数组中的指针被调用时它被调用。例如:

sample_struct_table[0].foo(...);

(显然用调用函数所需的参数替换省略号)。

长答案:C 可以有一个指向函数的指针,这意味着您可以加载共享对象(.dll、.so 等)并查找在运行时定义的函数,然后调用这些函数而无需链接到它们。这是非常强大的。如果您正在创建一个包含指向您的函数的指针的结构,那么只有当您想使用循环调用一系列函数时,这才是最有用的。我想如果结构的一部分是 int,则函数可以指定接下来要调用哪个函数,但我无法想象这会有用的场景。如果您熟悉 Scala 并且已经在系统中使用过它,那么这应该不难弄清楚,因为 Scala 一直都是这样做的。

scala> 1 to 10 foreach println

这里的 foreach 函数接受一个接受单个 Int 作为参数的函数。我们将 println 函数 (def println(x : Any) = ...) 作为参数传递给 foreach。

于 2012-12-10T23:47:38.137 回答
2

意外62,我认为您的困惑源于struct. 你认为那foo是 typeint吗?

我们有:

static struct sample_struct {
    int         command;
    int         (*foo)( obj1 *banana, int num);
} sample_struct_table[] = {
    {   .command    =   COMMAND_1,
        .foo =   function_name,
    },
    {   .command    =   COMMAND_2,
        .foo =   another_function_name,
    },
};

typedef我们可以使用s稍微重写一下。第一步:

typedef struct _sample_t
{
    int         command;
    int         (*foo)( obj1 *banana, int num);
} sample_t;

从那里到第二个:

typedef int (*foo_t)( obj1 *banana, int num);
typedef struct _sample_t
{
    int         command;
    foo_t       foo;
} sample_t;

foo如果您是 C 的新手,这应该可以更清楚地了解类型是什么。

现在,即使您声明和初始化了数组,您最终还是将数组初始化为两个函数的地址以及后面的文字COMMAND_1和 和COMMAND_2

现在假设您有以下程序(我即兴使用了这些值),您可以看到如何在函数for体的循环内调用main()函数。

#include <stdio.h>
#include <stdlib.h>

#define COMMAND_1 1
#define COMMAND_2 2
typedef void* obj1;
static int function_name(obj1 *banana, int num);
static int another_function_name(obj1 *banana, int num);

typedef int (*foo_t)( obj1 *banana, int num);
typedef struct _sample_t
{
    int         command;
    foo_t       foo;
} sample_t;

sample_t sample_struct_table[] = {
    {   .command    =   COMMAND_1,
        .foo =   function_name,
    },
    {   .command    =   COMMAND_2,
        .foo =   another_function_name,
    },
};

static int function_name(obj1 *banana, int num)
{
    // do stuff here
    // When does this get called?
    return 0;
}

static int another_function_name(obj1 *banana, int num)
{
    // do stuff here
    // When does this get called?
    return 0;
}

int main(int argc, char** argv)
{
    int i;
    for(i = 0; i < sizeof(sample_struct_table)/sizeof(sample_struct_table[0]); i++)
    {
        printf("%i\n", i);
        if(sample_struct_table[i].foo(NULL, i))
            return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

TL;博士:

调用一个函数,不像在 Pascal 中,总是需要说function_name(...),而function_name仅仅引用那个函数的地址。

于 2012-12-10T23:50:56.970 回答