简体   繁体   English

何时在C中初始化结构?

[英]When is a struct initialized in C?

I am new to C, from a Java background. 我是Java新手,来自Java背景。

If I have a struct that is initialized on the fly with data that comes from functions inside of the struct definition, when do those functions get called? 如果我有一个动态初始化的结构,其中的数据来自结构定义中的函数,那么这些函数什么时候被调用? When does this code run? 这段代码什么时候运行? Is it just on the first reference to sample_struct_table[i] ? 它只是第一次引用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?
}

The functions get called when you call them. 调用它们时会调用这些函数。 In your example, all you are doing is setting the field of the structure to the function pointer. 在您的示例中,您所做的只是将结构的字段设置为函数指针。 The function is not called, you just have a pointer pointing to it. 该函数未被调用,您只需指向它的指针。

Short answer: it gets called when the pointers in the array are called. 简短的回答:当调用数组中的指针时调用它。 For example: 例如:

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

(Obviously replacing the elipses with the parameters needed to call the function). (显然用调用函数所需的参数替换elipses)。

Long answer: C can have a pointer to a function, which means that you can load shared object (.dll, .so, etc) and look for functions defined at runtime, then call those functions with out ever linking to them. 答案很长:C可以有一个指向函数的指针,这意味着您可以加载共享对象(.dll,.so等)并查找在运行时定义的函数,然后调用这些函数,而不是链接到它们。 This is very powerful. 这非常强大。 If you are creating a struct that contains pointers to your functions, that is really most useful only if you want to call a series of functions using a loop. 如果要创建一个包含指向函数的指针的结构,那么只有在想要使用循环调用一系列函数时才最有用。 I suppose if a part of the struct were an int, the functions could specify which function to call next, but I can't imagine a scenario where this would be useful. 我想如果结构的一部分是一个int,那么函数可以指定接下来调用哪个函数,但是我无法想象这会有用的场景。 If you're familiar with Scala and have used it in a system, then this shouldn't be hard to figure out, as Scala does this all the time. 如果您熟悉Scala并在系统中使用它,那么这应该不难理解,因为Scala一直这样做。

scala> 1 to 10 foreach println

Here the foreach function accepts a function that accepts a single Int as a parameter. 这里foreach函数接受一个接受单个Int作为参数的函数。 We are passing the println function (def println(x : Any) = ...) as a parameter to foreach. 我们将println函数(def println(x:Any)= ...)作为参数传递给foreach。

unexpected62, I think your confusion stems from the definition of the struct . 意外62,我认为你的困惑源于struct的定义。 Do you think that foo is of type int , perhaps? 你认为foo的类型是int吗?

We have: 我们有:

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,
    },
};

We could rewrite this a little bit using typedef s. 我们可以使用typedef重写一下这个。 First step: 第一步:

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

And from there to, second: 从那里到第二个:

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

This should make it more obvious what the type of foo is, if you're new to C. 如果你是C的新手,这应该让foo的类型变得更加明显。

Now, even with your declaration and initialization of the array you end up with the array initialized to the address of the two functions plus the literals behind COMMAND_1 and COMMAND_2 respectively. 现在,即使您对数组进行声明和初始化,最终也会将数组初始化为两个函数的地址以及COMMAND_1COMMAND_2背后的文字。

Now assuming you have the following program (I improvised with the values), you can see how the functions can be called inside the for loop in the body of the main() function. 现在假设你有以下程序(我用值即兴创作),你可以看到如何在main()函数体内的for循环中调用这些函数。

#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: TL; DR:

Calling a function, unlike in Pascal, always requires to say function_name(...) , whereas function_name merely refers to the address of that function. 与Pascal不同,调用函数总是需要说function_name(...) ,而function_name只是引用该函数的地址。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM