The story of functional and function pointer types in C language

In C language, in addition to the function pointer type used for assignable variables, there is also a ** function type **. A function type is a type for a function (variable) in a function prototype declaration.

The function prototype declaration used when calling a function before the function definition appears is one of the ** declarations ** in C language, like the variable declaration.

/*Function pointer type variable declaration statement*/
int (* add_p)(int, int);

/*Function prototype declaration statement*/
int add(int, int);

By the way, this function name ʻadd` is also a variable in the C language syntax, but ** assignment is impossible ** (semantic error).


And the typedef statement is also a declaration statement. Function pointer type and function type typedef declarations are as follows.

/*Function pointer type typedef declaration statement*/
typedef int (* op_p)(int, int);

/*Function pointer type typedef declaration statement*/
typedef int op_t(int, int);

You can use the ** typedef name ** defined in the typedef declaration to describe the function pointer type variable declaration statement and the function prototype declaration statement.

/*Function pointer type variable declaration statement*/
op_p add_p;

/*Function prototype declaration statement*/
op_t add;

There are few cases where typedef is used for the latter prototype declaration, and many people may not know its existence.


You can also derive a function pointer type by using the functional type typedef name.

/*Function pointer type variable declaration statement*/
op_t * add_p;

/*Function pointer type typedef declaration statement*/
typedef op_t * op_p;

However, it is prohibited by design to use ** type qualifiers such as const and volatile (, restrict) in the function type itself. Of course, you can add a type qualifier to that pointer.

/*Incorrect variable declaration statement*/
const op_t * add_p = 0;

/*Correct function pointer type variable declaration statement*/
op_t * const add_p = 0;

In the former, both gcc and clang were warning levels, not compilation errors. (Because the const qualification attached to the target type of the pointer is ignored in the assignment (again with warning))


It is illegal to use a function or a functional variable (prototype declaration) in sizeof.

/*Illegal*/
size_t ftsize = sizeof (int (int, int));

int add(int, int);
/*Illegal*/
size_t fsize = sizeof add;

Both gcc and clang only issued a warning, and when I ran it, the result was 1.


Function types cannot be used as a return type of a function or as a member of struct / ʻunion` because they cannot be assigned.

However, function arguments allow you to write functional arguments. This is because the function type of a function's ** argument is treated as a pointer type **, just as the array type of a function's argument is treated as a pointer type.

/*op is a function pointer type*/
int apply(int op(int, int), int v) {
  return (*op)(v, v);
}
typedef int op_t(int, int);

/*op is a function pointer type*/
int apply(op_t op, int v) {
  return (*op)(v, v);
}

Reference: Code example using functional type that can be compiled and executed without warning

func-type-example.c


/* cc -std=c89 -pedantic -Wall -Wextra func-type-example.c */

/* types for function (prototype)  */
typedef int op2_t(int, int);

/* function prototype declaration with typedef types */
static op2_t add, sub;

/* types for function pointer */
typedef op2_t * op2_ptr1;
typedef int (* op2_ptr2)(int, int);

/* function type in parameter as function pointer type */
static int apply(op2_t op, int a, int b) {
  return (*op)(a, b);
}

extern int main() {
  const op2_ptr1 padd = &add;
  op2_t * psub = ⊂
  return padd(10, apply(psub, 2, 3)); /* echo $? => 9 */
}

/* K&R C style definition */
int add(a, b) int a; int b; {
  return a + b;
}

/* ANSI C style definition */
int sub(int a, int b)  {
  return a - b;
}

Recommended Posts