Function Pointers in C: Practical Examples and Best Practices
Function pointers unlock powerful capabilities in C, allowing functions to manipulate data directly through memory addresses rather than copying values. By passing addresses to pointer parameters, a function can modify the original variables, enabling patterns such as in‑place swapping, dynamic callbacks, and higher‑order functions.
- Function Pointers Example
- Functions with Array Parameters
- Functions that Return an Array
- Function Pointers
- Array of Function Pointers
- Functions Using void Pointers
- Function Pointers as Arguments
Function Pointers Example
The classic swap routine demonstrates how a function can exchange the values of two variables by operating on their addresses.
void swap (int *a, int *b);
int main() {
int m = 25;
int n = 100;
printf("m is %d, n is %d\n", m, n);
swap(&m, &n);
printf("m is %d, n is %d\n", m, n);
return 0;
}
void swap (int *a, int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}
Output:
m is 25, n is 100 m is 100, n is 25

- Declare
swapwith two integer pointers. - Initialize
mandninmainand print them. - Call
swap(&m, &n)to pass the addresses. - Inside
swap, use a temporary variable to exchange the values. - Dereference pointers to read/write the actual data.
Functions with Array Parameters
Arrays decay to pointers when passed to functions. The following program sums an array’s elements by iterating over the pointer.
int add_array (int *a, int num_elements);
int main() {
int Tab[5] = {100, 220, 37, 16, 98};
printf("Total summation is %d\n", add_array(Tab, 5));
return 0;
}
int add_array (int *p, int size) {
int total = 0;
for (int k = 0; k < size; k++) {
total += p[k]; /* equivalent to total += *p; p++; */
}
return total;
}
Output:
Total summation is 471

- Define
add_arrayto accept a pointer and size, returning the sum. - Pass the array name
Tab(which decays to a pointer) and its length to the function.
Functions that Return an Array
A function can return a pointer to a static array. This approach is useful when the caller needs a temporary array without managing memory allocation.
#include <stdio.h>
int * build_array();
int main() {
int *a;
a = build_array(); /* get first 5 even numbers */
for (int k = 0; k < 5; k++)
printf("%d\n", a[k]);
return 0;
}
int * build_array() {
static int Tab[5] = {1,2,3,4,5};
return Tab;
}
Output:
1 2 3 4 5

- Declare a function that returns a pointer to a static array.
- Use the returned pointer to iterate and print the array contents.
Function Pointers
A function pointer holds the address of a function’s entry point, allowing dynamic dispatch and callbacks. The declaration syntax requires parentheses around the asterisk to avoid misinterpretation.
return_type (*function_name)(arguments)
Example: Call a routine through a pointer.
#include <stdio.h>
void Hi_function (int times); /* function */
int main() {
void (*function_ptr)(int); /* function pointer */
function_ptr = Hi_function; /* assignment */
function_ptr(3); /* invocation */
return 0;
}
void Hi_function (int times) {
for (int k = 0; k < times; k++)
printf("Hi\n");
}
Output:
Hi Hi Hi

- Define a regular function.
- Declare a function pointer with the correct signature.
- Assign the pointer to the function’s name.
- Invoke the function through the pointer.
Array of Function Pointers
Storing multiple function pointers in an array enables a table‑driven approach, similar to a switch statement. The following program demonstrates a simple calculator.
#include <stdio.h>
int sum(int num1, int num2);
int sub(int num1, int num2);
int mult(int num1, int num2);
int divi(int num1, int num2);
int main() {
int x, y, choice, result;
int (*ope[4])(int, int);
ope[0] = sum;
ope[1] = sub;
ope[2] = mult;
ope[3] = divi;
printf("Enter two integer numbers: ");
scanf("%d%d", &x, &y);
printf("Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: ");
scanf("%d", &choice);
result = ope[choice](x, y);
printf("%d", result);
return 0;
}
int sum(int x, int y) {return x + y;}
int sub(int x, int y) {return x - y;}
int mult(int x, int y) {return x * y;}
int divi(int x, int y) {return y != 0 ? x / y : 0;}
Result: Enter 13 48 2 → 624

- Define four arithmetic functions.
- Create an array of four function pointers with matching signatures.
- Assign each pointer to the corresponding function.
- Retrieve the user’s choice and call the selected function.
Functions Using void Pointers
Void pointers provide type‑agnostic access to data. When used in function parameters, they allow the routine to accept any data type, provided the caller supplies the correct cast.
void * cube (const void *);
Example program:
#include <stdio.h>
void* cube (const void* num);
int main() {
int x = 4;
int cube_int = (int)cube(&x);
printf("%d cubed is %d\n", x, cube_int);
return 0;
}
void* cube (const void *num) {
int result = (*(int *)num) * (*(int *)num) * (*(int *)num);
return (void*)result;
}
Result: 4 cubed is 64

- Define a function that accepts a const void pointer and returns a void pointer.
- Cast the pointer to
int *to access the value. - Compute the cube and cast the result back to
void *for return.
Function Pointers as Arguments
Passing a function pointer to another function is a common pattern for callbacks. The standard library’s qsort uses this technique to sort arrays of arbitrary types.
void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *));
Example that sorts an integer array:
#include <stdio.h>
#include <stdlib.h>
int compare (const void *, const void *);
int main() {
int arr[5] = {52, 14, 50, 48, 13};
size_t num = sizeof(arr)/sizeof(arr[0]);
size_t width = sizeof(arr[0]);
qsort((void *)arr, num, width, compare);
for (size_t i = 0; i < num; i++)
printf("%d ", arr[i]);
return 0;
}
int compare (const void *elem1, const void *elem2) {
int a = *(int *)elem1;
int b = *(int *)elem2;
return (a - b);
}
Result: 13 14 48 50 52

- Implement
compareto return negative, zero, or positive based on the two integers. - Determine array size and element width with
sizeof. - Call
qsortwith the array, count, width, and comparison function. - Print the sorted array to verify the operation.
C Language
- Mastering User-Defined Functions in C: A Step‑by‑Step Guide
- Four Proven Patterns for User‑Defined Functions in C
- Mastering C++ Pointers: Concepts, Examples & Practical Applications
- C++ Functions Explained with Practical Code Examples
- C# Hashtable Explained: Key-Value Storage, Operations, and Practical Examples
- Understanding Switch‑Case in C: Syntax, Examples, and Best Practices
- Master C Functions: Practical Examples of Recursion & Inline Techniques
- Master Python Lambda Functions: Practical Examples & Best Practices
- Mastering C Functions: Structure, Declaration, and Best Practices
- Master Python Extension Programming with C: Build Fast, Native Modules