Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does a typedef with parenthesis like "typedef int (f)(void)" mean? Is it a function prototype?

Tags:

c

typedef

typedef int (fc_name) (void); 

Here fc_name is any valid C symbol.

How different is this from a function pointer typedef?

like image 653
Hemanth Avatar asked Sep 09 '10 06:09

Hemanth


People also ask

What is the function of a typedef?

A typedef, or a function-type alias, helps to define pointers to executable code within memory. Simply put, a typedef can be used as a pointer that references a function.

What does typedef VOID do?

5/19: "The void type comprises an empty set of values; it is an incomplete object type that cannot be completed.". void has no size; it has no values; and there is absolutely no technical reason why you would ever need to create a typedef for it.

What is a typedef statement?

A typedef declaration is a declaration with typedef as the storage class. The declarator becomes a new type. You can use typedef declarations to construct shorter or more meaningful names for types already defined by C or for types that you have declared.

Does typedef need semicolon?

typedef interpretation is performed by the compiler where #define statements are performed by preprocessor. #define should not be terminated with a semicolon, but typedef should be terminated with semicolon.


2 Answers

It's a typedef to a function type. The intent is to use it for function pointers, but in this case the syntax to use it would be:

int bar(void);  fc_name* foo = bar; /* Note the * */ 

Update: As mentioned in the comments to Jonathan Leffler's answer, the typedef can be used to declare functions. One use could be for declaring a set of callback functions:

typedef int (callback)(int, void*);  callback onFoo; callback onBar; callback onBaz; callback onQux; 
like image 67
jamesdlin Avatar answered Sep 28 '22 08:09

jamesdlin


The first parentheses are superfluous - it is equivalent to:

typedef int fc_name(void); 

I don't think this does anything useful, though I can't get GCC to complain about it on its own.

This means that fc_name is an alias for a function type that takes no arguments and returns an int. It isn't directly all that useful, though you can declare, for example, the rand() function using:

fc_name rand; 

You cannot use the typedef in a function definition.

A pointer to function typedef would read:

typedef int (*fc_name)(void); 

This code shows that the typedefs without the asterisk are not function pointers (addressing a now-deleted alternative answer):

static int function(void) {     return 0; }  typedef int   fc_name1 (void); typedef int  (fc_name2)(void); typedef int (*fc_name3)(void);  fc_name1 x = function; fc_name2 y = function; fc_name3 z = function; 

When compiled, 'gcc' says:

gcc -Wextra -Wall -pedantic -c -O x.c x.c:10:1: error: function ‘x’ is initialized like a variable x.c:11:1: error: function ‘y’ is initialized like a variable 

And this code demonstrates that you can indeed use fc_name *var = funcname; as suggested by jamesdlin:

static int function(void) {     return 0; }  typedef int   fc_name1 (void); typedef int  (fc_name2)(void); typedef int (*fc_name3)(void);  fc_name1  x_0 = function; fc_name1 *x_1 = function; fc_name2  y_0 = function;    // Damn Bessel functions - and no <math.h> fc_name2 *y_1 = function;    // Damn Bessel functions - and no <math.h> fc_name3  z   = function; 

Using y0, y1 generates GCC warnings:

x.c:12:11: warning: conflicting types for built-in function ‘y0’ x.c:13:11: warning: built-in function ‘y1’ declared as non-function 

And, building on the comment from schot:

static int function(void) {     return 0; }  typedef int   fc_name1 (void); typedef int  (fc_name2)(void); typedef int (*fc_name3)(void);  fc_name1  x_0 = function;   // Error fc_name1 *x_1 = function;   // x_1 is a pointer to function fc_name1  x_2;              // Declare int x_2(void); fc_name1 *x_3 = x_2;        // Declare x_3 initialized with x_2  fc_name2  y_0 = function;   // Damn Bessel functions - and no <math.h> fc_name2 *y_1 = function;   // Damn Bessel functions - and no <math.h> fc_name1  y_2;              // Declare int y_2(void); fc_name1 *y_3 = x_2;        // Declare y_3 initialized with y_2  fc_name3  z   = function; 

Interesting - the dark corners of C are murky indeed.

like image 42
Jonathan Leffler Avatar answered Sep 28 '22 09:09

Jonathan Leffler