Thursday, November 17, 2011

Hiding the Implementation of a Struct in C

As a novice C programmer, I've been learning a lot of interesting things lately. One thing I've just learned is that you can hide the implementation of a struct by declaring it as a typedef for a struct that does not exist, and then using only pointers to it in the header file. The actual struct is defined in the implementation file, and its internal structure is completely hidden. The only problem with this of course is that you must provide some way of getting and setting fields in the structure, which is a pain Java programmers know well.

In the .h file you might have a line like:

typedef struct Point_t Point;

Which is implemented in the .c file as:

struct Point_t {
int x;
int y;
};
Then you need functions like:


int point_get_x(Point *point) {return point->x;}
int point_get_y(Point *point) {return point->y;}
void point_set_x(Point *point, int x) {point->x = x;}
void point_set_y(Point *point, int y) {point->y = y;}

So, why would we go through all this trouble just to hide things from users? First off, some people really like hiding things from other people- its easier to change implementation details and it can assist separation of concerns. On the other hand, it can also make code hard to understand and debug, and take control away from the user. On yet a third hand, it may be necessary for structural reasons like something I ran into recently.

For a project I'm working on, I've wrapped an API in a slightly higher-level API to make it more palatable for its users. This wrapper makes use of types defined by the API which I don't want to expose to the end-user, who should not have to interact with the low level API at all. The problem is that I have structs whose fields include structs defined in the lower level API. This means that the user can't access the structs directly without having at least the header files from the base program, which I want to avoid mostly cause it feels messy as if information is leaking out of my abstraction.

To fix this problem, I've hidden the implementation and exposed only getters (aka accessors) and setters (aka mutators) for the fields that I want the user to be able to control. The details are tedious, but it does give you a more fine grained way to expose information and it does hide the details of the underlying implementation better than I was before.

So I hope that was a little bit interesting- there is plenty of further reading found by googling "struct hiding in c" that gives more details and examples.

1 comment:

  1. I'm liking these entries about C. I can actually understand most of what your talking about, though at a lower level. For instance, I know structs and I've used them several times, but never knew that you could use them to hide details. Pretty cool.

    ReplyDelete