How to define function type with typedef?
Asked Answered
B

4

5

I would like to know if it is possible to define a function type using typedef, I tried this syntax:

typedef int (*) (void *, void *) order;

But it doesn't work. Error message : expected identifier or '(' before ')' token

Burgess answered 25/11, 2019 at 11:2 Comment(1)
Possible duplicate of Understanding typedefs for function pointers in CCiri
E
15

The alias name should be placed where a variable name would be if it was a variable declaration.

Here:

typedef int (*order) (void *, void *);
//            ^~~~~

Or, if you want a function type rather than a pointer-to-function:

typedef int order(void *, void *);
Emilyemina answered 25/11, 2019 at 11:4 Comment(7)
What is the reason behind declaring a function type?Burgess
@ThunderPheonix It's not very useful. You could use it to declare functions: order foo; -> int foo(void*, void*);. Or, if you add a star, function pointers: order *ptr; (the pointer-to-function typedef does the same thing without the star).Emilyemina
Actually I need a pointer to a function in order to do a cast when calling qsort function.Burgess
@ThunderPheonix I thought you were asking about functions vs pointers-to-functions. In any case, casting a function to a function pointer that has different parameter types or return type is a bad idea, and calling the resulting pointer causes undefined behavior (see C11 6.3.2.3/8).Emilyemina
I just wanted to avoid the warning message of qsort!Burgess
@ThunderPheonix Make sure the function you pass to it looks like int name(const void *, const void *). Then you wouldn't need a cast.Emilyemina
Actually my function takes two struct element as parameter and compare them according to struct members. So it looks like int comp (const struct element *, const struct element *). And it worked well. I don't understand why it is a bad idea to do a cast?Burgess
P
6

This typedef

typedef int (*order )(void *, void *);

defines an alias for the type of pointer to function of the type int( void *, void * ).

This typedef

typedef int order(void *, void *);

defines an alias for the type of function of the type int( void *, void * ).

If to use one typedef to define both the alias for pointer and the alias for function you can write

typedef int ( *porder )( void *, void * ), order(void *, void *);

or even the following way

int typedef ( *porder )( void *, void * ), order(void *, void *);

Pay attention to that you can use either typedef name as a type specifier for a function parameter. For example these two declarations

void h( porder arg );
void h( order arg );

declare the same one function because the compiler adjusts implicitly the type of a parameter having a function type to pointer to the function type.

However you may not use interchangeably these typedef(s) for the function return type because functions may not return functions but they may return pointers to functions. So this declaration

porder h( void );

will compile. But this declaration

order h( void );

will not compile.

Without the typedef the declaration of a function that returns pointer to other function would be complicated. For example this declaration

porder h( void );

without the typedef looks like

int ( *h( void ) )( void *, void * );
Picturesque answered 25/11, 2019 at 11:7 Comment(6)
@Lundin I showed this example because in the answer of glglgl there was shown an invalid construction of a typedef for both declarators.Picturesque
Still you would never write them on the same line.Flosser
@Flosser Be calm. Syntax training exercises are very important to better understand language constructsPicturesque
Not if you don't point out that a certain syntax is bad practice. Before you know it, you'll have newbies writing code like int* x, (*y)(int), z;.Flosser
Yeah so if even a veteran programmer can't get it right, it says something about how bad and infrequently used that syntax is...Flosser
your last example is useful ... I found some declarations of function returning pointer to function in OpenSSL that I simply could not understandCarton
C
2

You do either of

typedef int (*order) (void *, void *);
typedef int order(void *, void *);

depending on if you want to typedef the function or the pointer.

Both has advantages and disadvantages; I prefer a style where a pointer is visible as such and have my functions defined as

order order_impl;
int order_impl(void * a, void * b)
{
}
order * order_pointer = order_impl;

This ensures that the function is defined properly.

Others, however, prefer working with the function pointer type and do

porder order_pointer = order_impl;

and live without the said safeguard, leaving them with only a warning instead of an error in the case of a mismatch.

Clustered answered 25/11, 2019 at 11:4 Comment(0)
F
2

You declare a function pointer just like a function, except you wrap the function name in parenthesis and write a * in front of the name.

void func (void);              // function
void (*func) (void);           // pointer to function
typedef void (*func) (void);   // pointer to function type

However, my recommended style is one that doesn't hide pointers behind a typedef:

typedef int order_t (void*, void*);
...
order_t* order; 

The typedef is a function template and the declaration is a function pointer declaration of that type. This makes function pointer syntax consistent with object pointers.

Flosser answered 25/11, 2019 at 11:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.