何时在C中初始化结构?

时间:2012-12-10 23:28:28

标签: c

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

如果我有一个动态初始化的结构,其中的数据来自结构定义中的函数,那么这些函数什么时候被调用?这段代码什么时候运行?它只是第一次引用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?
}

3 个答案:

答案 0 :(得分:6)

调用它们时会调用这些函数。在您的示例中,您所做的只是将结构的字段设置为函数指针。该函数未被调用,您只需指向它的指针。

答案 1 :(得分:3)

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

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

(显然用调用函数所需的参数替换elipses。)

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

scala> 1 to 10 foreach println

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

答案 2 :(得分:2)

意外62,我认为你的困惑源于struct的定义。您是否认为foo类型为int

我们有:

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;

如果您是C的新手,这应该使foo的类型更加明显。

现在,即使您对数组进行声明和初始化,最终还是将数组初始化添加到两个函数的地址加上COMMAND_1COMMAND_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; DR:

与Pascal不同,调用函数始终需要说function_name(...),而function_name仅指代该函数的地址。