A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
Standard C does not allow functions defined inside other functions. GCC supports nested functions as an extension. A nested function can access the local variables of its enclosing function, similar to a closure in higher-level languages. This is convenient but non-portable. The implementation uses trampolines on the stack, which creates executable stack pages and conflicts with security hardening. For portable code, use function pointers with a context struct instead.
#include <stdio.h>void outer(void) {int offset = 100;void inner(int x) {printf("inner(%d) -> %d (offset=%d)\n", x, x + offset, offset);}inner(5);inner(10);offset = 200;inner(5);}int main(void) {outer();return 0;}
inner accesses offset from the enclosing scope. When offset changes, inner sees the new value. This is closure behavior. It works because GCC generates a trampoline: a small piece of executable code on the stack that sets up the enclosing frame pointer before jumping to inner's body. This requires an executable stack, which modern security policies (NX bit, SELinux) may prohibit.
#include <stdio.h>typedef struct {int offset;} Context;typedef int (*transform_fn)(int x, void *ctx);int add_offset(int x, void *ctx) {Context *c = (Context *)ctx;return x + c->offset;}void apply(transform_fn fn, void *ctx, int *arr, int n) {for (int i = 0; i < n; i++) {arr[i] = fn(arr[i], ctx);}}int main(void) {Context ctx = {100};int data[] = {1, 2, 3, 4, 5};apply(add_offset, &ctx, data, 5);printf("Result: ");for (int i = 0; i < 5; i++) printf("%d ", data[i]);printf("\n");return 0;}
The context struct carries the captured state. The function pointer provides the behavior. The apply function is generic: it works with any transform function and any context. This is the C idiom for callbacks, event handlers, and comparators. It is portable to every C compiler. It does not require an executable stack. It is the pattern used by qsort, pthread_create, and every C library that accepts callbacks.
Nested functions are a convenience that costs portability and security. The function-pointer-plus-context pattern achieves the same result with standard C. Use it. It scales from simple callbacks to complex event systems. Next: finding the middle index without integer overflow, a subtle bug that appears in binary search implementations.
Finish the lesson once you have worked through the material. This awards ★ 30 XP.