Practical Implementation
Real-World Function Pointer Patterns
Function pointers are versatile tools with numerous practical applications in system programming, event handling, and modular design.
Design Patterns
1. Command Pattern Implementation
typedef struct {
void (*execute)(void* data);
void* context;
} Command;
void execute_command(Command* cmd) {
if (cmd && cmd->execute) {
cmd->execute(cmd->context);
}
}
Event Handling Mechanism
#define MAX_HANDLERS 10
typedef void (*EventHandler)(void* data);
typedef struct {
EventHandler handlers[MAX_HANDLERS];
int handler_count;
} EventDispatcher;
void register_event_handler(EventDispatcher* dispatcher, EventHandler handler) {
if (dispatcher->handler_count < MAX_HANDLERS) {
dispatcher->handlers[dispatcher->handler_count++] = handler;
}
}
void dispatch_event(EventDispatcher* dispatcher, void* event_data) {
for (int i = 0; i < dispatcher->handler_count; i++) {
dispatcher->handlers[i](event_data);
}
}
Callback Strategy Patterns
Pattern |
Description |
Use Case |
Strategy Pattern |
Dynamic algorithm selection |
Runtime behavior modification |
Observer Pattern |
Event notification |
Loose coupling between components |
Plugin Architecture |
Dynamic module loading |
Extensible systems |
Advanced Function Pointer Techniques
Function Pointer Arrays
typedef int (*MathOperation)(int, int);
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; }
MathOperation math_ops[] = {add, subtract, multiply};
int apply_operation(int x, int y, int op_index) {
if (op_index >= 0 && op_index < sizeof(math_ops) / sizeof(math_ops[0])) {
return math_ops[op_index](x, y);
}
return 0;
}
State Machine Implementation
stateDiagram-v2
[*] --> Idle
Idle --> Processing: Start Event
Processing --> Completed: Success
Processing --> Error: Failure
Completed --> [*]
Error --> [*]
Callback-Based Asynchronous Processing
typedef void (*CompletionCallback)(int result, void* context);
typedef struct {
void* data;
CompletionCallback on_complete;
void* context;
} AsyncTask;
void process_async_task(AsyncTask* task) {
// Simulate async processing
int result = /* processing logic */;
if (task->on_complete) {
task->on_complete(result, task->context);
}
}
Error Handling and Logging Mechanism
typedef enum {
LOG_INFO,
LOG_WARNING,
LOG_ERROR
} LogLevel;
typedef void (*LogHandler)(LogLevel level, const char* message);
void log_message(LogHandler handler, LogLevel level, const char* message) {
if (handler) {
handler(level, message);
}
}
- Minimize indirection overhead
- Use inline functions when possible
- Prefer static function pointers
- Avoid complex pointer arithmetic
Compilation and Optimization
## Compile with additional warnings
gcc -Wall -Wextra -O2 function_pointer_example.c -o example
## Enable function pointer safety checks
gcc -fsanitize=address function_pointer_example.c -o example
At LabEx, we recommend practicing these patterns to develop robust and flexible C applications using function pointers.