Function Pointer in C

Jinku Hu Oct 12, 2023
  1. Use void (*func)() Notation to Define Function Pointer in C
  2. Use Function Pointer Array to Implement Type-Generic Programming Feature
Function Pointer in C

This article will introduce how to use a function pointer in C.

Use void (*func)() Notation to Define Function Pointer in C

Function pointers are yet another construct in C programming that implement advanced features like dynamic function calling, structures that include their own methods similar to object-oriented design, type-generic programming and etc.

Note that function pointer declaration can have complicated syntax, namely, void (*func)(void) notation declares the pointer to void function that takes no parameters. Although we assign the address of printInt function, that takes a single int argument to the void (*func)(void) type function pointer in the following example.

Once the function pointer named func is defined, it can be called with the usual function call notation func(arg) or with dereferencing operator (*func)(arg).

#include <stdio.h>
#include <stdlib.h>

void printInt(int x) { printf("printed from printInt: %d\n", x); }

int main() {
  int input1 = 10233;

  void (*func)(int) = printInt;

  func(input1);
  (*func)(input1);

  exit(EXIT_SUCCESS);
}

Output:

printed from printInt: 10233
printed from printDouble: 11.234000

Alternatively, we can define a new type alias of a function pointer using typedef to make code more readable. Note that different function types would need separate typedef statements.

In the following code sample, we define a pointer to a void function without any arguments; nonetheless, both printInt and printDouble function addresses are stored in the variable of type FuncPtr.

It should be noted out that the address of the specific function can be taken with explicit & operator or with the implicit assignment of function name itself, as demonstrated in the next example.

#include <stdio.h>
#include <stdlib.h>

typedef void (*FuncPtr)();

void printInt(int x) { printf("printed from printInt: %d\n", x); }

void printDouble(double x) { printf("printed from printDouble: %f\n", x); }

int main() {
  int input1 = 10233;
  double input2 = 11.234;

  FuncPtr func1 = printInt;
  FuncPtr func2 = printDouble;

  func1(input1);
  func2(input2);

  exit(EXIT_SUCCESS);
}

Output:

printed from printInt: 10233
printed from printDouble: 11.234000

Use Function Pointer Array to Implement Type-Generic Programming Feature

Like other objects, one can define an array of function pointers with brackets [] notation. This array can be utilized to choose and call specific functions during run-time easily.

Notice that we are using the keyword _Generic, which is switch like an expression that lets the user choose the specific case base on the type evaluation of the controlling expression.

Consequently, we implement the following code example, where the corresponding print function is called based on the type of the variable passed in the switch condition. Note that, enum type is also utilized to define constant values for different cases.

#include <stdio.h>
#include <stdlib.h>

enum TYPE { INTEGER, DOUBLE, INVALID };

#define typename(x) \
  _Generic((x), int: INTEGER, double: DOUBLE, default: INVALID)

typedef void (*FuncPtr)();

void printInt(int x) { printf("printed from printInt: %d\n", x); }

void printDouble(double x) { printf("printed from printDouble: %f\n", x); }

int main() {
  int input1 = 10233;
  double input2 = 11.234;

  FuncPtr func_ptrs[] = {printInt, printDouble};

  switch (typename(input1)) {
    case INTEGER:
      func_ptrs[INTEGER](input1);
      break;
    case DOUBLE:
      func_ptrs[DOUBLE](input1);
      break;
    case INVALID:
      printf("No corresponding type found!\n");
    default:
      break;
  }

  switch (typename(input2)) {
    case INTEGER:
      func_ptrs[INTEGER](input2);
      break;
    case DOUBLE:
      func_ptrs[DOUBLE](input2);
      break;
    case INVALID:
      printf("No corresponding type found!\n");
    default:
      break;
  }

  exit(EXIT_SUCCESS);
}

Output:

printed from printInt: 10233
printed from printDouble: 11.234000
Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Related Article - C Pointer