I know this question might have been asked before but I wanted to take my approach at it and get an opinion or possibly a better way to do it.
I have three files a.h
a.c
and main.c
Prototypes of functions regarding the struct will be in a.h
while implementation will be in a.c
and called from main.c
the structure will be simple it can just look like this
struct ctx{
int x;
};
I want a.c
to be able to manipulate the contents of the struct but prevent main from having any idea of what's inside. So I figured placing the struct definition inside a.c
instead of a.h
and placing just struct ctx;
as a prototype in a.h
And this could work, however ctx can no longer be allocated on the stack in main.c
because the compiler doesn't know the size to allocate.
So this leads me to my first question: Is there a way to allocate the structure local to the stack without knowing the definition of the structure.
So I assumed if it wasn't possible on the stack then maybe I could just pass it on the heap instead by creating a simple init function that returns a pointer. And that does work but would it be over complicating the process?
a.h
#ifndef a_h
#define a_h
#include <stdio.h>
#include <stdlib.h>
struct ctx;
int incctx(struct ctx* c);
struct ctx* initctx(void);
void destroyctx(struct ctx* c);
#endif /* a_h */
a.c
#include "a.h"
struct ctx{
int x;
};
int incctx(struct ctx* c){
return ++c->x;
}
struct ctx* initctx(){
struct ctx* c = malloc(sizeof(struct ctx));
c->x = 0;
return c;
}
void destroyctx(struct ctx* c){
free(c);
}
main.c
#include "a.h"
int main(){
struct ctx* c = initctx();
printf("%d\n",incctx(c));
printf("%d\n",incctx(c));
printf("%d\n",incctx(c));
destroyctx(c);
return 0;
}
This design kind of solves the problem with a few drawbacks.
1: What if I wanted to make parts of the structure visible but not the entire thing?
2: If I wanted the structure definition to be available to other files say b.h
and b.c
would I have to redefined the structure? Do any of you have a cleaner design? I know some people say you can just place a void*
in the structure instead of specific types and just label them arbitrary names but I don't see that as a viable solution.