boltup_im_coding
boltup_im_coding

Reputation: 6665

When is a struct initialized in C?

I am new to C, from a Java background.

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]?

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?
}

Upvotes: 2

Views: 147

Answers (3)

0xC0000022L
0xC0000022L

Reputation: 21369

unexpected62, I think your confusion stems from the definition of the struct. Do you think that foo is of type int, perhaps?

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 typedefs. 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.

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.

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.

#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:

Calling a function, unlike in Pascal, always requires to say function_name(...), whereas function_name merely refers to the address of that function.

Upvotes: 2

wingman
wingman

Reputation: 56

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).

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. 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. 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> 1 to 10 foreach println

Here the foreach function accepts a function that accepts a single Int as a parameter. We are passing the println function (def println(x : Any) = ...) as a parameter to foreach.

Upvotes: 3

RonaldBarzell
RonaldBarzell

Reputation: 3830

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.

Upvotes: 6

Related Questions