That would be my preference. And contrary to what others thought that one would want a lot of these loops, when you want only a few, especially when those few are fixed for the entire program life you can do better by avoiding malloc altogether.
Could be my preference for working on systems that never malloc and only use specific pools and rely on knowing their exact memory requirements from the start to the end. I can acknowledge that this may be more anal than normal but then if the library didn't allocate in my name I could choose to allocate on heap or use it in a static fashion as I please.
As an undergrad I was thought about ADT (Abstract Data Type) and then the "proper" way was to provide a _new method to allocate the data. This also allowed to completely hide the type as the C header didn't need to show the content of the struct being allocated.
If you go with not malloc'ing internally then you need to expose the entire struct and I tend to go about it by using an extra header X_internal.h that is explicitly showing the internals but expects you not to abuse this knowledge.
It's a tradeoff and I currently tend towards the second option more often than not.
Could be my preference for working on systems that never malloc and only use specific pools and rely on knowing their exact memory requirements from the start to the end. I can acknowledge that this may be more anal than normal but then if the library didn't allocate in my name I could choose to allocate on heap or use it in a static fashion as I please.