- typedef struct { ... } foo
- foo *foo_create()
- void foo_destroy(foo *)
- a bunch of functions that take foo* as their first arg
which is kind of the same as a class and only more error-prone.
I say this as someone who actually _likes_ C, but the manual memory management model is very often unnecessary, confusing, repetitive. There was an idea some time ago of a language extension that would extend the concept of automatic storage duration to allow an explicit destructor to be called when the variable goes out of scope, like <close> variables in some languages. I genuinely think things like that would make the language a bit more ergonomic without fundamentally changing its nature.