Hierarchical Programming in C Using Nested Structs and Function Pointers
Hierarchical Programming in C Using Nested Structs and Function Pointers
By Arlon Arriola – Santa Cruz Web Factory
Welcome to my take on how you can write hierarchically structured programs in pure C, even without classes or native inner classes like in Java. I built this framework early in my systems programming course (CST 334) to test what was possible using only function pointers and nested structs.
It’s a C-style hierarchy: struct t6
defines the program structure, and struct t6 t5
instantiates and runs it. I wanted something Java-like — logical, readable, extensible. Something that encourages organized thinking and clean growth from the start. Otherwise, C projects can devolve into spaghetti code fast.
Why this structure?
I read many threads that said you “can’t define functions inside structs” in C, and that’s technically true — but only if you're thinking like a C++ or Java dev. C lets you assign function pointers to structs, and if you're clever with GCC’s statement expressions, you can build what feels like a class hierarchy.
Here’s what I found and how it led me to this paradigm:
- Google: C add function to struct
- Stack Overflow: Can I define a function inside a C structure?
- Define functions in structs
- Working example of function pointer-based "methods"
- Anonymous functions using GCC statement expressions
- What are nested structures in C?
None of the above gave me the structure I was after — but they gave me the pieces. I put them together.
Example: My Struct-Based Framework in C
Below is the full source code of my implementation. It builds a multi-level, fully nestable C framework using struct nesting and inline function pointer initialization.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int program() {
struct t6 {
int (*add)(int, int);
struct inner0 {} inner0_0;
struct inner1 {} inner0_1;
struct inner2 {
struct inner3 {} inner0_3;
struct codeFights {
struct cF0 {
int (*add)(int, int);
int (*centuryFromYear)(int);
int (*checkPalindrome)(char *);
} cF00;
} codeFights_0;
struct colors {
struct console {
struct gnulinux {
struct ansi {
char * (*color)(int);
char * (*random)(int);
char * (*randomFG)();
char * (*randomBG)();
char * (*reset)();
} ansi;
} gnulinux;
} console;
} colors;
} inner0_2;
struct program {
struct data {} data;
struct state {} state;
struct api {
struct tricks {
struct codeFights2 {
int (*adjacentElementsProduct)(int *, int);
} codeFights2;
} tricks;
struct mo {
int (*zero)();
int (*one)();
int (*two)();
} mo;
} api;
struct init {
int (*zero)();
} init;
} program;
};
struct t6 t5 = {
({ int f(int x, int y) { return x + y; } f; }),
{},
{},
{
{},
{
{
({ int f(int x, int y) { return x + y; } f; }),
({ int f(int year) { return 1 + (year - 1)/100; } f; }),
({ int f(char *inputString) {
for (int i = 0; i < strlen(inputString)/2; i++) {
if (inputString[i] !=
inputString[strlen(inputString)-1-i])
return 0;
}
return 1;
} f; })
}
},
{
{
{
{
({
char * f(int color) {
static char buf[32];
snprintf(buf, sizeof(buf), "\033[0;%dm", color);
return buf;
} f;
}),
({
char * f(int bg) {
time_t t; srand((unsigned)time(&t));
int base = bg ? 40 : 30;
int c = base + (rand() % 8);
static char buf[32];
snprintf(buf, sizeof(buf), "\033[0;%dm", c);
return buf;
} f;
}),
({
char * f() { return
t5.inner0_2.colors.console.gnulinux.ansi.random(0); } f;
}),
({
char * f() { return
t5.inner0_2.colors.console.gnulinux.ansi.random(1); } f;
}),
({
char * f() {
static char buf[8];
snprintf(buf, sizeof(buf), "\033[0m");
return buf;
} f;
})
}
}
}
}
},
{
{},
{},
{
{
{
({
int f(int *arr, int len) {
int max = arr[0] * arr[1];
for (int i = 1; i < len - 1; i++) {
int prod = arr[i] * arr[i+1];
if (prod > max) max = prod;
}
return max;
} f;
})
}
},
{
({
int f() {
struct t4 { int (*add)(int, int); };
struct t4 t = ({ int f(int x, int y) { return x + y; } f; });
printf("Add: %d\n", t.add(1, 2));
return 1;
} f;
}),
({
int f() {
printf("Century from 2021: %d\n"
, t5.inner0_2.codeFights_0.cF00.centuryFromYear(2021));
printf("Is 'abba' a palindrome? %d\n"
, t5.inner0_2.codeFights_0.cF00.checkPalindrome(\"abba\"));
return 1;
} f;
}),
({
int f() {
return 1;
} f;
})
}
},
{
({
int f() {
t5.program.api.mo.one();
return 1;
} f;
})
}
}
};
t5.program.init.zero();
return 0;
}
int main() {
program();
return 0;
}
Final Thoughts
This structure was primarily an experiment — to see how far I could push plain C into an organized, hierarchical paradigm. While it does rely on GNU extensions (statement expressions), it compiles and runs cleanly, and it’s intuitive if you're coming from object-oriented backgrounds.
That said, I’m not a C expert — I built this for learning, exploration, and potential future use. So if you do choose to build off it, please test thoroughly for memory safety, especially with more complex pointer logic or dynamic memory.
If you're curious about where I used this or how it came to be, check out the project and related writing here:
https://arlonarriola.com/?school/csumb/ilp/cst-334
— Arlon Arriola
Please also see: Stack Overflow: Can I define a function inside a C structure?