Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

typedef a function interface (not function pointer)

If I typedef like this:

typedef int (read_proc_t)(char *page, char **start, off_t off,
                          int count, int *eof, void *data);

as defined here

What is this technique called?

If I typedef this way, which means I create a type read_proc_t; later, I create my own version of read-proc-t, which is my_read_proc and I have a struct like this:

struct test {
    read_proc_t read_proc;
} 

struct test t;

I can do something like this:

t.read_proc_t = my_read_proc;

Is this correct? Normally, if I typedef read_proc_t as a function pointer:

typedef int (*read_proc_t)(char *page, char **start, off_t off,
                          int count, int *eof, void *data);

I would have to assign my_read_proc function address to the function pointer, like this:

(*t.read_proc_t) = &my_read_proc;

In which circumstance do I choose one?

like image 568
Amumu Avatar asked Dec 01 '25 00:12

Amumu


1 Answers

The difference is that in the first case the type read_proc_t does not get an implicit pointer semantic, while in the second case it becomes a pointer type.

The difference between the two is that the variables of the first type cannot be created in most contexts. For example, it is illegal to define the struct like this:

struct test {
    // This causes an error in C99:
    // field ‘read_proc’ declared as a function
    read_proc_t read_proc;
};

You need an asterisk to make it valid:

struct test {
    read_proc_t *read_proc;
};

However, read_proc_t can be used to declare function parameters:

void read_something(read_proc_t rd_proc) {
    rd_proc(...); // Invoke the function
}

There is a certain degree of interchangeability between read_proc_t and read_proc_t*: for example, you can call the above function like this:

read_proc_t *rd = my_read_01;
read_something(rd); // <<== read_proc_t* is passed to read_proc_t

In general, you should prefer the first declaration to keep the function pointer semantic explicit, because it is better for readability. If you use the second declaration (with an asterisk) you should name the type in a way that tells the reader that it is a pointer, for example, like this:

typedef int (*read_proc_ptr_t)(char *page, char **start, off_t off,
                      int count, int *eof, void *data);
like image 55
Sergey Kalinichenko Avatar answered Dec 03 '25 15:12

Sergey Kalinichenko