Definition
The Command Pattern encapsulates a request or action as a standalone object, decoupling the component that triggers the operation from the component that executes it. In C, this is achieved using structs containing function pointers, execution state, and context data. It enables request queuing, logging, macro-commands, undo/redo functionality, and clean separation of input/UI handling from business logic without relying on object-oriented inheritance or virtual dispatch.
Core Components & Mechanics
| Component | C Implementation | Role |
|---|---|---|
| Command | struct with function pointers (execute, undo) and context/state | Encapsulates the action, parameters, and execution contract |
| Receiver | Target data/object the command operates on | Performs the actual work (e.g., file, device, buffer, hardware register) |
| Invoker | Queue, scheduler, or input handler | Stores commands and calls execute() without knowing implementation details |
| Client | Code that creates and configures commands | Binds receiver to command, sets parameters, passes to invoker |
Implementation Example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Base Command Interface (simulated via consistent struct layout)
typedef struct {
void (*execute)(void *ctx);
void (*undo)(void *ctx);
void *ctx;
const char *name;
} Command;
// Concrete Receiver Context
typedef struct {
char buffer[64];
size_t length;
char last_char;
} TextBuffer;
// Command Operations
void insert_char(void *ctx) {
TextBuffer *tb = ctx;
if (tb->length < sizeof(tb->buffer) - 1) {
tb->last_char = tb->buffer[tb->length];
tb->buffer[tb->length++] = 'X';
printf("Inserted 'X', len=%zu\n", tb->length);
}
}
void undo_insert(void *ctx) {
TextBuffer *tb = ctx;
if (tb->length > 0) {
tb->buffer[--tb->length] = tb->last_char;
printf("Undo insert, len=%zu\n", tb->length);
}
}
// Invoker
typedef struct {
Command *stack[32];
int top;
} CommandQueue;
void invoke(CommandQueue *cq, Command *cmd) {
if (cq->top < 32) cq->stack[cq->top++] = cmd;
if (cmd->execute) cmd->execute(cmd->ctx);
}
void undo_last(CommandQueue *cq) {
if (cq->top > 0) {
Command *cmd = cq->stack[--cq->top];
if (cmd->undo) cmd->undo(cmd->ctx);
}
}
int main(void) {
TextBuffer tb = { .buffer = "Hello", .length = 5 };
Command insert_cmd = {
.execute = insert_char,
.undo = undo_insert,
.ctx = &tb,
.name = "Insert X"
};
CommandQueue queue = { .top = 0 };
invoke(&queue, &insert_cmd);
invoke(&queue, &insert_cmd);
undo_last(&queue);
printf("Final: %.*s\n", (int)tb.length, tb.buffer);
return 0;
}
Rules & Constraints
- Function Pointer Matching:
executeandundomust matchvoid (*)(void *)exactly. Mismatched signatures invoke undefined behavior. - Context Lifetime: Commands do not own context by default. If a command outlives its context, use-after-free occurs.
- No Automatic Polymorphism: C lacks vtables. Uniform command handling requires explicit struct layout consistency or wrapper macros.
- Memory Management: Stack-allocated commands suit synchronous, short-lived operations. Heap allocation is required for async queues, logging, or undo histories.
- Thread Safety: Not inherently thread-safe. Shared command queues require mutexes or lock-free atomic pointers.
- Undo State Capture: Each command must explicitly snapshot or reverse state. Generic undo is impossible without reflection or serialization.
Best Practices
- Standardize the command struct: Use a single base layout for all commands to enable uniform queuing and invoker design.
- Validate function pointers:
if (cmd && cmd->execute) cmd->execute(cmd->ctx);prevents NULL dereferences. - Document context ownership: Clearly state whether the command, invoker, or client is responsible for allocating/freeing the context.
- Use memory pools for queues: Fixed-size arrays or slab allocators prevent heap fragmentation in embedded or real-time systems.
- Implement idempotent commands: Design
execute()to safely handle repeated invocations when appropriate (e.g., network retries). - Separate command creation from execution: Use factory functions or builder patterns to keep client code clean and maintainable.
Common Pitfalls
- đŽ Uninitialized function pointers: Forgetting to assign
executeorundoâ segmentation fault on invocation. - đŽ Context dangling: Invoker holds command pointer after context is freed â use-after-free and memory corruption.
- đŽ Assuming automatic undo: Undo requires explicit state reversal per command type. Missing implementation causes inconsistent state.
- đŽ Memory leaks in dynamic queues: Allocating commands on heap but forgetting to free them during cleanup or queue reset.
- đŽ Global state mutation: Commands modifying globals break reentrancy, prevent undo correctness, and complicate testing.
- đŽ Over-engineering with inheritance: Simulating OOP vtables in C adds complexity and overhead. Simple function pointers + context structs are sufficient.
- đŽ Ignoring reentrancy/interrupt safety: Queue manipulation inside ISRs without atomic guards causes race conditions or deadlocks.
Standards & Tooling
- Language Support: Pure architectural pattern. Works identically across C89, C99, C11, C17, and C23. No standard library dependency.
- Compiler Diagnostics:
-Wmissing-field-initializers,-Wnull-dereference, and-Wstrict-prototypescatch setup errors and signature mismatches. - Static Analysis:
clang-tidy,cppcheck, andCoveritydetect uninitialized function pointers, context lifetime violations, and unsafe queue operations. - Debugging: GDB/LLDB resolve function pointer targets to symbols.
print cmd.executeshows implementation address and symbol name.ptype Commandverifies layout. - Industry Usage: Embedded RTOS task schedulers, GUI frameworks (LVGL, GTK signal/callback routing), game engine input systems, CLI parsers, and undo/redo stacks in editors.
- Modern Alternatives: C23
_Genericenables compile-time command dispatch for known types. For high-throughput systems, ring buffers with index-based command tables reduce pointer indirection overhead.
The Command Pattern in C provides a disciplined, low-overhead approach to request decoupling, queue management, and state reversal. By leveraging consistent struct layouts, explicit function pointers, and careful context lifecycle management, developers can implement robust, testable, and extensible control flows without sacrificing C's performance or portability guarantees.
Complete C Programming Guide + Compilers Collection
1. C srand() Function â Understanding Seed Initialization
https://macronepal.com/understanding-the-c-srand-function
Explains how srand() initializes the pseudo-random number generator in C by setting a seed value. Using the same seed produces the same sequence, while time(NULL) gives different results each run.
2. C rand() Function Mechanics and Limitations
https://macronepal.com/c-rand-function-mechanics-and-limitations
Explains how rand() generates pseudo-random numbers between 0 and RAND_MAX, its deterministic nature, and limitations for security use cases.
3. C log() Function
https://macronepal.com/c-log-function-2
Covers natural logarithm calculation using <math.h> and its applications.
4. Mastering Date and Time in C
https://macronepal.com/mastering-date-and-time-in-c
Explains <time.h> functions like time(), clock(), difftime(), and struct tm.
5. Mastering time_t Type in C
https://macronepal.com/mastering-the-c-time_t-type-for-time-management
Explains time representation as seconds since Unix epoch and conversion functions.
6. C exp() Function
https://macronepal.com/c-exp-function-mechanics-and-implementation
Explains exponential function exp(x) and its scientific applications.
7. C log() Function (Alternate Guide)
https://macronepal.com/c-log-function
Comparison of log() and log10() with usage examples.
8. C log10() Function
https://macronepal.com/mastering-the-log10-function-in-c
Explains base-10 logarithm for engineering and scientific applications.
9. C tan() Function
https://macronepal.com/understanding-the-c-tan-function
Explains tangent function and radian-based calculations.
10. Random Numbers in C (Secure vs Predictable)
https://macronepal.com/mastering-c-random-numbers-for-secure-and-predictable-applications
Explains difference between rand() and secure randomness methods.
11. Free Online C Compiler
https://macronepal.com/free-online-c-code-compiler-2
Browser-based compiler for testing C programs instantly.
C Functions, Arguments, Parameters & Flow
Mastering Functions in C â Complete Guide
https://macronepal.com/c/mastering-functions-in-c-a-complete-guide/
Covers function structure, modular programming, and real-world usage.
Function Arguments in C
https://macronepal.com/c-function-arguments/
Explains how arguments are passed and used in function calls.
Function Parameters in C
https://macronepal.com/c-function-parameters/
Explains defining inputs for functions and matching them with arguments.
Function Declarations in C
https://macronepal.com/c-function-declarations-syntax-rules-and-best-practices/
Covers prototypes, syntax rules, and best practices.
Function Calls in C
https://macronepal.com/understanding-function-calls-in-c-syntax-mechanics-and-best-practices/
Explains execution flow and parameter handling during function calls.
Void Functions in C
https://macronepal.com/understanding-void-functions-in-c-syntax-patterns-and-best-practices/
Explains functions that do not return values.
Return Values in C
https://macronepal.com/c-return-values-mechanics-types-and-best-practices/
Explains different return types and how functions return results.
Pass-by-Value in C
https://macronepal.com/aws/understanding-pass-by-value-in-c-mechanics-implications-and-best-practices/
Explains how copies of variables are passed into functions.
Pass-by-Reference in C
https://macronepal.com/c/understanding-pass-by-reference-in-c-pointers-semantics-and-safe-practices/
Explains using pointers to modify original variables.
C strstr() Function
https://macronepal.com/aws/c-strstr-function/
Explains substring search inside strings in C.
C Preprocessor & Macros
https://macronepal.com/mastering-c-variadic-macros-for-flexible-debugging/
https://macronepal.com/mastering-the-stdc-macro-in-c/
https://macronepal.com/c-time-macro-mechanics-and-usage/
https://macronepal.com/understanding-the-c-date-macro/
https://macronepal.com/c-file-type/
https://macronepal.com/mastering-c-line-macro-for-debugging-and-diagnostics/
https://macronepal.com/mastering-predefined-macros-in-c/
https://macronepal.com/c-error-directive-mechanics-and-usage/
https://macronepal.com/understanding-the-c-pragma-directive/
https://macronepal.com/c-include-directive/
C Structures, Memory, Scope & Linkage
https://macronepal.com/mastering-structures-in-c/
https://macronepal.com/c-structure-declaration-mechanics-and-usage/
https://macronepal.com/c-structure-initialization-mechanics-and-best-practices/
https://macronepal.com/mastering-c-structure-member-access-for-reliable-data-handling/
https://macronepal.com/c-nested-structures/
https://macronepal.com/mastering-arrays-of-structures-in-c/
https://macronepal.com/c-structure-pointers-mechanics-and-implementation/
https://macronepal.com/understanding-c-structure-parameter-passing-mechanics/
https://macronepal.com/mastering-c-returning-structures-for-efficient-data-flow/
https://macronepal.com/c-self-referential-structures/
https://macronepal.com/mastering-structure-alignment-in-c/
https://macronepal.com/c-structure-padding-mechanics-and-optimization/
https://macronepal.com/understanding-c-flexible-array-members-mechanics-and-usage/
https://macronepal.com/mastering-c-anonymous-structures-for-flattened-data-layouts/
https://macronepal.com/c-unions/
https://macronepal.com/mastering-c-name-mangling-and-symbol-decoration/
https://macronepal.com/c-no-linkage-mechanics-and-scope-isolation/
https://macronepal.com/understanding-c-internal-linkage-mechanics-and-architecture/
C Scope, Storage Classes & Typedef
https://macronepal.com/mastering-function-prototype-scope-in-c/
https://macronepal.com/c-function-scope-mechanics-and-visibility/
https://macronepal.com/understanding-c-file-scope-mechanics-and-architecture/
https://macronepal.com/mastering-c-scope-rules-for-predictable-name-resolution/
https://macronepal.com/c-scope-rules/
https://macronepal.com/mastering-c-register-storage-class-for-historical-context-and-modern-alternatives/
https://macronepal.com/mastering-_thread_local-in-c/
https://macronepal.com/c-extern-storage-class-mechanics-and-usage/
https://macronepal.com/understanding-the-c-static-storage-class-mechanics-and-usage/
https://macronepal.com/c-auto-storage-class/
https://macronepal.com/c-typedef-with-pointers/
Extra Articles
https://macronepal.com/13757-2/
https://macronepal.com/13748-2/
https://macronepal.com/13747-2/
https://macronepal.com/13746-2/
https://macronepal.com/13745-2/
https://macronepal.com/13708-2/
https://macronepal.com/13707-2/
https://macronepal.com/13702-2/
Online Compilers
https://macronepal.com/free-html-online-code-compiler/
https://macronepal.com/free-online-python-code-compiler/
https://macronepal.com/free-online-python2-code-compiler/
https://macronepal.com/free-online-java-code-compiler/
https://macronepal.com/free-online-javascript-code-compiler/
https://macronepal.com/free-online-node-js-code-compiler/
https://macronepal.com/free-online-c-code-compiler/
https://macronepal.com/free-online-c-code-compiler-2/
https://macronepal.com/free-online-c-code-compiler-3/
https://macronepal.com/free-online-php-code-compiler/
https://macronepal.com/free-online-ruby-code-compiler/
https://macronepal.com/free-online-perl-code-compiler/
https://macronepal.com/free-online-lua-code-compiler/
https://macronepal.com/free-online-tcl-code-compiler/
https://macronepal.com/free-online-groovy-code-compiler/
https://macronepal.com/free-online-j-shell-code-compiler/
https://macronepal.com/free-online-haskell-code-compiler/
https://macronepal.com/free-online-scala-code-compiler/
https://macronepal.com/free-online-common-lisp-code-compiler/
https://macronepal.com/free-online-d-code-compiler/
https://macronepal.com/free-online-ada-code-compiler/
https://macronepal.com/free-erlang-code-compiler/
https://macronepal.com/free-online-assembly-code-compiler/
https://macronepal.com/c-unions/
https://macronepal.com/mastering-c-anonymous-structures-for-flattened-data-layouts/
https://macronepal.com/understanding-c-flexible-array-members-mechanics-and-usage/
https://macronepal.com/c-structure-padding-mechanics-and-optimization/
https://macronepal.com/mastering-structure-alignment-in-c/
https://macronepal.com/c-self-referential-structures/
https://macronepal.com/mastering-c-returning-structures-for-efficient-data-flow/
https://macronepal.com/understanding-c-structure-parameter-passing-mechanics/
https://macronepal.com/c-structure-pointers-mechanics-and-implementation/
https://macronepal.com/mastering-arrays-of-structures-in-c/
https://macronepal.com/c-nested-structures/
