I am starting a side project in C which requires multiple storage backends to be driven by a particular piece of logic. These storage backends would each be linked with the decision of which one to use specified at runtime.So for example if I invoke my program with one set of parameters it will perform the operations in memory but if I change the program configuration it would write to disk.The underlying idea is that each storage backend should implement the same protocol. In other words the logic for performing operations should need to know which backend it is operating on.Currently the way I have thought to provide this indirection is to have a struct of function pointers with the logic calling these function pointers. Essentially the struct would contain all the operations needed to implement the higher level logic E.g.struct Context {    void (* doPartOfDoOp)(void)    int (* getResult)(void); }//logic.hvoid doOp(Context * context) {    //bunch of stuff    context->doPartOfDoOp();}int getResult(Context * context) {    //bunch of stuff    return context->getResult();} My questions is if this way of solving the problem is one a C programmer would understand? I am a Java developer by trade but enjoy using C/++. Essentially the Context struct provides an interface like level of indirection. However I would like to know if there is a more idiomatic way of achieving this.
C programming multiple storage backends
c;interfaces
Yes, a seasoned C programmer would certainly understand such constructs. Using function pointers is just about the only way you have in C to select at runtime which of a set of functions to execute.Ans storing function pointers in a struct gives a very clear signal that those functions belong together and is a very common way to emulate methods/member-functions in C.One change I would advise is to pass the Context struct also as a 'this pointer' to the function pointers, like this:struct Context {    void (* doPartOfDoOp)(struct Context*)    int (* getResult)(struct Context*); };//logic.hvoid doOp(Context * context) {    //bunch of stuff    context->doPartOfDoOp(context);}int getResult(Context * context) {    //bunch of stuff    return context->getResult(context);}In C, if you have a pointer to the first member of a struct, then you can cast that pointer to the struct type itself and use it to access the other members. This allows you to build a kind of inheritance tree and makes it possible to give your back-ends member variables, like this:struct FileBackend {    struct Context interface;    FILE* file;}void doPartOfDoOpFileBackend(struct Context* context){    struct FileBackend* this = (struct FileBackend)context;    // do stuff, accessing the file through this->file.}