coopheader-filesinformation-hiding

Properly hiding functions from the external context of the module


I'm attempting to implement information hiding in C in a OO fashion. Since C obviously doesn't provide access modifiers such as public, private and protected, the solution I was able to come up with is to define an abstract data type (which attributes shouldn't be visible outside) in a *.c file, and to put in the corresponding header file a typedef which only refers to this new data type.

The header file also contains the prototypes of my public functions and therefore works as the public interface of this data type. There's also another header file which lists the protected functions which I don't want to be visible in normal circumstances. The *.c file then contains the implementation of every functions, including some that aren't listed in neither header files. These are my private functions.

LinkedList.h

#ifndef LINKEDLIST_H_
#define LINKEDLIST_H_

typedef struct LinkedList LinkedList;

LinkedList* newLinkedList();

#endif

LinkedList_protected.h

#ifndef LINKEDLIST_PROTECTED_H_
#define LINKEDLIST_PROTECTED_H_

#include "Node.h"
#include "LinkedList.h"

Node* getFirstNode(LinkedList* self);

Node* getLastNode(LinkedList* self);

#endif

LinkedList.c

#include "LinkedList.h"
#include "LinkedList_protected.h"
#include "Node.h"

// PRIVATE

struct LinkedList {

    Node* first;
    Node* last;
    unsigned int nodesNo;

};

void privateTest() {

    printf("Test");

}

// PROTECTED

Node* getFirstNode(LinkedList* self) {

    return self->first;
}

Node* getLastNode(LinkedList* self) {

    return self->last;

}

// PUBLIC

LinkedList* newLinkedList() {

    LinkedList* self = malloc(sizeof(LinkedList));

    self->first = NULL;
    self->last = NULL;

    self->nodesNo = 0;

    return self;

}

This seems to work: attempting to access the attributes of LinkedList in another module gives me an error ("dereferencing pointer to incomplete type"), which is what I wanted. However, referring to a private or even protected function just gives me a "implicit declaration" warning. Why is that? Should I worry about it? Also, is this solution safe and could it be improved?


Solution

  • C is a very old language. When it was invented computers where slow and had very little memory, cpu power and even disk space. CPU time also cost real money. Having to include headers, parse them and remember all the functions declared there would have been a drain with real costs.

    So to simplify things the compiler just assumed that if you call a function that that function will exist and take the argument types you use when calling and and that it would return int. That's an "implicit declaration". Simply calling the function implicitly declares it. This feature exists to this day.

    So it's not so much that the compiler somehow sees those protected/private functions but it simply and blindly assumes they exist and, surprise, when you later link the object files together they do.

    Check your compiler documentation on how to turn this warning into an error. While totally legal it's a very dangerous feature (implicit declaration skip any type checks by their nature and fail for anything not returning ) and you really shouldn't use this feature nowadays. Having the compile fail when someone tries to use it seems like what you want.