我是来自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?
}
答案 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_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; DR:
与Pascal不同,调用函数始终需要说function_name(...)
,而function_name
仅指代该函数的地址。