Indirection, pointer casting, and the C standard library actually make things quite opaque in practice. Do you sbrk your own memory or use malloc? Malloc may not be as mysterious as GC, but it’s still a runtime-managed resource.
You can replace malloc with your own implementation. Just have a big static array to dole out bits of memory. The loader or startup code will prep it for you.