Back to C Programming
2025-12-258 min read

22.5.2 Assigning Function Pointers

Learn 22.5.2 Assigning Function Pointers step by step with clear examples and exercises.

Why This Matters

Function pointers are an essential aspect of C programming that provide greater flexibility and modularity in your code. They enable functions to be treated as first-class citizens, allowing for advanced topics such as callbacks, event-driven programming, and dynamic function dispatch. Understanding function pointers can help you excel in system programming, library development, application development, and even during interviews.

Prerequisites

Before diving into assigning function pointers, it is essential to have a solid grasp of the following concepts:

  • Basic C syntax and data types
  • Function declarations and definitions
  • Pointers and pointer arithmetic
  • Arrays and pointers
  • Understanding of the stack and heap memory allocation in C
  • Familiarity with recursive functions

Core Concept

Declaring a Function Pointer

To declare a function pointer, we specify its return type and the types of its arguments. The general syntax is as follows:

return_type (*function_name)(argument1_type argument1, ...);

For example, if we have a function add() that takes two integers as arguments and returns their sum, we can declare a pointer to this function like so:

int (*binary_op)(int, int) = NULL; // Declare a pointer to a function taking two integers and returning an integer

Assigning a Function Pointer

To assign a function to a function pointer, we can either use the address-of operator & or simply reference the function name without parentheses:

binary_op = add; // Assign the address of the 'add' function to the 'binary_op' pointer
binary_op = &add; // Alternatively, assign the address of the 'add' function to the 'binary_op' pointer using the address-of operator

Calling a Function Through a Pointer

Once we have assigned a function to a function pointer, we can call that function using the dereference operator * and passing the arguments in parentheses:

result = (*binary_op)(num1, num2); // Call the function pointed to by 'binary_op' with arguments num1 and num2

Function Pointers and Arrays

Function pointers can also be stored in arrays, allowing us to perform operations on multiple functions at once. To declare an array of function pointers, we simply use the [] operator:

int (*operations[4])(int, int) = { NULL, add, subtract, multiply }; // Declare an array of 4 function pointers for binary operations on integers

Function Pointers and Structures

Function pointers can be stored within structures to create more complex data types. This is particularly useful when dealing with objects that have multiple methods or functions associated with them.

typedef struct {
int (*operation)(int, int); // Declare a function pointer member in the structure
int id;
} calculator_t;

calculator_t my_calculator = { add, 1 }; // Create a calculator object with 'add' as its operation and an ID of 1

Recursive Function Pointers

Recursive functions can be pointed to using function pointers. This allows for the creation of recursive function libraries or the implementation of recursive algorithms with user-defined entry points.

typedef int (*recursive_function)(int); // Declare a recursive function pointer type

recursive_function fibonacci = fib; // Assign the address of the 'fib' recursive function to the 'fibonacci' pointer
int result = (*fibonacci)(num); // Call the recursive function pointed to by 'fibonacci' with an argument 'num'

Worked Example

Let's create a simple program that uses function pointers to perform different mathematical operations:

#include <stdio.h>

int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
int divide(int a, int b) { return a / b; }

void print_options() {
printf("Choose an operation:\n");
printf("1. Add\n");
printf("2. Subtract\n");
printf("3. Multiply\n");
printf("4. Divide\n");
}

int main() {
int (*binary_op)(int, int) = NULL; // Declare a function pointer for binary operations
int num1, num2;

print_options(); // Print options for the user to choose an operation
scanf("%d", &operation); // Read user input for the desired operation

switch (operation) {
case 1:
binary_op = add;
break;
case 2:
binary_op = subtract;
break;
case 3:
binary_op = multiply;
break;
case 4:
binary_op = divide;
break;
default:
printf("Invalid option.\n");
return -1;
}

printf("Enter two numbers to perform the operation:\n");
scanf("%d %d", &num1, &num2); // Read user input for the first and second operands
int result = (*binary_op)(num1, num2); // Perform the selected operation using the function pointer
printf("Result: %d\n", result); // Print the result to the console

return 0;
}

Common Mistakes

  1. Forgetting the parentheses when calling a function through a pointer: Remember to use (*binary_op)(arguments) instead of binary_op(arguments).
  2. Incorrect function prototype or return type: Ensure that the function prototype matches the function definition, and that the function pointer's return type is compatible with the actual function's return type.
  3. Not initializing the function pointer: Always initialize a function pointer to NULL or an appropriate value before assigning it a function address.
  4. Misunderstanding pointer arithmetic: Be careful when using function pointers in loops, as they are not simple integers and have specific memory addresses associated with them.
  5. Not understanding upward compatibility: The target type of the function pointer must be compatible with the function's return type (upward compatible).
  6. Not handling NULL or undefined function pointers: Be sure to check if a function pointer is NULL before calling it, and avoid using undefined functions.
  7. Using function pointers as simple pointers for data: Function pointers are not the same as regular pointers; they store addresses of functions, not arbitrary memory locations.
  8. Not understanding recursive function pointers: Recursive function pointers require special care when handling stack frames and memory allocation. Be sure to understand how recursion works in C before using recursive function pointers.
  9. Not properly managing memory with dynamic function allocation: When dynamically allocating function pointers, be aware of potential memory leaks and ensure proper deallocation using free().
  10. Misusing function pointers for control flow: Function pointers should primarily be used to pass functions as arguments or return values from functions. Misusing them for control flow can lead to confusing and hard-to-debug code.

Practice Questions

  1. Write a program that uses function pointers to perform the operations of addition, subtraction, multiplication, and division on two floating-point numbers.
  2. Modify the example program to handle user-defined functions for the mathematical operations.
  3. Create a library that provides a set of mathematical functions (addition, subtraction, multiplication, and division) and allows users to create custom calculator objects with their preferred operation order.
  4. Write a function that sorts an array of structures containing integers using a provided comparison function (function pointer).
  5. Create a program that uses function pointers to implement a simple game where the user can choose between different strategies for playing rock-paper-scissors against the computer.
  6. Implement a recursive function using a function pointer to calculate the Fibonacci sequence up to a given number.
  7. Write a program that dynamically allocates memory for an array of function pointers and initializes them with user-defined functions. The program should then call each function in the array and print their results.
  8. Create a simple event-driven programming example using function pointers, where different functions are called based on user input events (e.g., mouse clicks or keyboard presses).

FAQ

Q: Why do we need function pointers in C?

A: Function pointers allow us to write flexible, modular code by enabling functions to be passed as arguments to other functions or returned as values from other functions. They are essential for advanced topics such as callbacks and event-driven programming.

Q: Can I use function pointers with void functions?

A: Yes, you can declare a function pointer that points to a void function. However, since there is no return value, you cannot call the function using the standard (*function_pointer)(arguments) syntax. Instead, you should use the function pointer as an argument in a function call or cast it to another function type with a return value.

Q: How can I check if a function pointer is NULL?

A: You can compare a function pointer with NULL using the equality operator (==). For example, if (binary_op == NULL).

Q: Can I pass a function pointer as an argument to another function and have it modify the original function pointer inside that function?

A: Yes, you can achieve this by passing the address of the function pointer using the address-of operator (&). Inside the called function, you can then modify the function pointer. However, be aware that modifying a function pointer can lead to unintended consequences if not handled carefully.

Q: How does the compiler know the size of a function pointer?

A: The size of a function pointer depends on the target architecture and is typically determined at compile-time by the compiler. In C, the size of a function pointer is always sufficient to store the address of any valid function.

Q: Can I use function pointers with arrays or structures?

A: Yes, you can store function pointers in arrays and structures to create more complex data types. This allows for greater flexibility and modularity in your code.

Q: How does the linker handle multiple definitions of a function when using function pointers?

A: When multiple functions have the same name but different definitions, the linker will choose one definition based on the order of inclusion in the source files or by explicitly specifying the desired function using an external linkage attribute (extern). It is important to ensure that all function definitions match their respective prototypes and that there are no conflicting names.

Q: Can I use function pointers for polymorphism in C?

A: While C does not have the same level of polymorphism as object-oriented languages like Java or C++, function pointers can be used to achieve a form of polymorphism through dynamic dispatch. This involves calling functions based on their type at runtime using function pointers. However, this approach is more limited than true object-oriented polymorphism and requires careful management of memory and function addresses.