Master C Function Pointers and Callbacks: Concepts, Syntax, and Real‑World Examples
This article explains C function pointers—from basic declaration and typedef usage to calling functions, passing pointers as parameters for callbacks, returning pointers from functions, and creating pointer arrays—illustrated with complete code samples and practical use cases.
Function Pointers Overview
A function pointer is a variable that holds the address of a function. Its declaration uses the form return_type (*pointer_name)(parameter_list). Parentheses around the pointer name are required; without them the declaration becomes a function returning a pointer.
/* Simple examples */
int (*Fun1)(int); /* pointer to int f(int) */
int (*Fun2)(int, int); /* pointer to int f(int, int) */
void (*Fun3)(void); /* pointer to void f(void) */
void *(*Fun4)(void *); /* pointer to void* f(void*) */Using typedef makes complex signatures easier to read:
typedef int (*Fun1)(int);
typedef int (*Fun2)(int, int);
typedef void (*Fun3)(void);
typedef void *(*Fun4)(void *);Assigning and Invoking Functions via Pointers
Assign the function name (which evaluates to its address) to the pointer and call it either with the dereference operator or directly:
#include <stdio.h>
int Max(int x, int y) { return x > y ? x : y; }
int main(void) {
int (*p)(int, int) = Max; /* or = &Max */
int a, b, c;
printf("enter a and b: ");
scanf("%d%d", &a, &b);
c = (*p)(a, b); /* same as c = p(a, b); */
printf("max = %d
", c);
return 0;
}Function Pointers as Parameters (Callbacks)
Define a function‑pointer type and pass a concrete function to another function:
#include <stdio.h>
typedef void (*FunType)(int);
void myFun(int x) { printf("myFun: %d
", x); }
void hisFun(int x) { printf("hisFun: %d
", x); }
void herFun(int x) { printf("herFun: %d
", x); }
void callFun(FunType fp, int x) { fp(x); }
int main(void) {
callFun(myFun, 100);
callFun(hisFun, 200);
callFun(herFun, 300);
return 0;
}Function Pointers as Return Types
A function can return a pointer to another function. The following prototype returns a pointer to a function taking two int arguments and returning void:
void (*func5(int, int, float))(int, int) {
/* implementation */
return NULL; /* placeholder */
}Arrays of Function Pointers
Function pointers can be stored in arrays, either directly or via a typedef:
/* Method 1 */
void (*func_array_1[5])(int, int, float);
/* Method 2 */
typedef void (*p_func_array)(int, int, float);
p_func_array func_array_2[5];Practical Callback Example – Arithmetic Operations
A struct groups pointers to basic arithmetic functions. After initialization, the program can invoke the operations directly or through a generic wrapper.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
float (*p_add)(float, float);
float (*p_sub)(float, float);
float (*p_mul)(float, float);
float (*p_div)(float, float);
} OP;
float ADD(float a, float b) { return a + b; }
float SUB(float a, float b) { return a - b; }
float MUL(float a, float b) { return a * b; }
float DIV(float a, float b) { return a / b; }
void init_op(OP *op) {
op->p_add = ADD;
op->p_sub = SUB;
op->p_mul = MUL;
op->p_div = DIV;
}
float apply(OP *op, float a, float b, float (*func)(float, float)) {
return func(a, b);
}
int main(void) {
OP *op = malloc(sizeof(OP));
init_op(op);
printf("ADD = %f, SUB = %f, MUL = %f, DIV = %f
",
apply(op, 1.3f, 2.2f, op->p_add),
apply(op, 1.3f, 2.2f, op->p_sub),
apply(op, 1.3f, 2.2f, op->p_mul),
apply(op, 1.3f, 2.2f, op->p_div));
free(op);
return 0;
}Real‑World Callback Use – GPRS Module State Machine
A state‑machine struct contains a status code and a function pointer. An array of such structs drives the workflow by invoking the appropriate function for each network state.
#include <stdint.h>
typedef struct {
uint8_t mStatus;
uint8_t (*Function)(void);
} M26_WorkStatus_TypeDef;
M26_WorkStatus_TypeDef M26_WorkStatus_Tab[] = {
{GPRS_NETWORK_CLOSE, M26_PWRKEY_Off},
{GPRS_NETWORK_OPEN, M26_PWRKEY_On},
{GPRS_NETWORK_Start, M26_Work_Init},
/* ... other states ... */
{GPRS_NETWORK_RESTART, M26_RESET}
};
uint8_t M26_WorkStatus_Call(uint8_t Start) {
for (int i = 0; i < 12; ++i) {
if (Start == M26_WorkStatus_Tab[i].mStatus) {
return M26_WorkStatus_Tab[i].Function();
}
}
return 0;
}Key Takeaways
Function pointers store addresses of functions; parentheses in the declaration are mandatory. typedef creates readable aliases for complex pointer signatures.
Callbacks are implemented by passing a function pointer to another function, allowing the callee to invoke user‑provided behavior.
Function pointers can be returned from functions, placed in arrays, or embedded in structs for flexible designs such as state machines.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
