C Command Pattern

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

ComponentC ImplementationRole
Commandstruct with function pointers (execute, undo) and context/stateEncapsulates the action, parameters, and execution contract
ReceiverTarget data/object the command operates onPerforms the actual work (e.g., file, device, buffer, hardware register)
InvokerQueue, scheduler, or input handlerStores commands and calls execute() without knowing implementation details
ClientCode that creates and configures commandsBinds 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: execute and undo must match void (*)(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

  1. Standardize the command struct: Use a single base layout for all commands to enable uniform queuing and invoker design.
  2. Validate function pointers: if (cmd && cmd->execute) cmd->execute(cmd->ctx); prevents NULL dereferences.
  3. Document context ownership: Clearly state whether the command, invoker, or client is responsible for allocating/freeing the context.
  4. Use memory pools for queues: Fixed-size arrays or slab allocators prevent heap fragmentation in embedded or real-time systems.
  5. Implement idempotent commands: Design execute() to safely handle repeated invocations when appropriate (e.g., network retries).
  6. 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 execute or undo → 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-prototypes catch setup errors and signature mismatches.
  • Static Analysis: clang-tidy, cppcheck, and Coverity detect uninitialized function pointers, context lifetime violations, and unsafe queue operations.
  • Debugging: GDB/LLDB resolve function pointer targets to symbols. print cmd.execute shows implementation address and symbol name. ptype Command verifies 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 _Generic enables 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/

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper