Myths and reality of the C programming language
The Internet is the first thing that humanity built and that humanity does not understand, the greatest experiment in anarchy in our entire history.
-- Эрик Шмидт
Contents
Context
Very often someone somewhere on some forum complains about the lack of encapsulation and isolation in C programming language. This happens with such regularity that I intend to debunk this myth once and for all. That way, the next time someone makes a similar claim, I can just link to this page instead of writing the explanation all over again.
It must be said that C is an old language that lacks many modern features. But what it lacks is encapsulation and isolation.
Let’s look at the definition of a class that has members private
; after all, that’s how isolation occurs, right? If all the fields were public, then it would be simple Cbut with inheritance1.
-
This is sarcasm, so relax.
class StringBuilder {
private String payload;
public void Append(String snippet) {
payload = payload + snippet;
}
};
Any attempt by a party to access the field payload
will result in a compile error. Quite convenient. You understand when it can be useful.
In a programming language C there are no classes, but there are struct
which look like this:
struct StringBuilder {
char *payload;
};
void Append(struct StringBuilder *obj, const char *snippet);
It has no access modifiers; all fields in the structure are public. That is why someone always complains about the lack of C encapsulation or isolation: everything in the structure is visible to everyone and always, even calls functions of functions Append()
.
Reality
But this complaint is not always justified. Although you of course you can drop everything into one source code file and be done with it, most often the code is divided into different files and modules.
When the code is in different source code files, they are encapsulated in the module. Every “module» in C consists of an interface file that callers can use to call functions found in the file’s implementation.
Interface file header file (With extension .h
) is this contractwhich tells the user of the module what functions and types are needed to use the implementation called quite often source code file. After compilation, you get a compiled one realizationand thus you may not have access to the source code Append()
.
And… yes!
Calling programs obliged use header file to fulfill legal (according to standards C) of challenges Append()
; after all, the implementation may only be available in compiled form, not in source code.
Therefore, in the header we do the following:
typedef struct StringBuilder StringBuilder;
void Append(StringBuilder *obj, const char *snippet);
And the implementation is as follows:
struct StringBuilder {
char *payload;
};
void Append(StringBuilder *obj, const char *snippet)
{
...
}
That’s it All!
Now any code that uses a type structure StringBuilder
will be able to use whatever it needs to create a string, but will never see the strings inside it.
But he won’t even be able to do it malloc()
for your own copy StringBuilder
because even the size is hidden StringBuilder
. It will have to use the create and delete functions provided in the implementation and specified in the interface.
But that’s not all…
So now we have the ability to create an instance of an object whose fields are all hidden from any calling party. At the same time, you have prevented all callers from tampering with the fields of your object – all access to the object is protected by functions in the implementation (as stated in the header).
We do not have an imitation, however is one very important feature: you can create objects from this class and use them even in Python.
Or in PHP.
And even in Ruby.
This will work with most Lisp implementations.
They can be called from Java.
Actually, I don’t think any of the common programming languages can not use this object. In many cases, a programmer in this language won’t even have to work very hard to use this class2.
-
See swig
In my Makefiles
there are already rules automatic generation of the interface, so that the code written in this manner on C could be called from Android apps.
Okay, you got it all, it’s time to wrap up
This is how you can get encapsulation and isolation in C with reliable guarantees. Don’t believe everything you read on the internet3.
-
Besides my blog, of course. Obviously, I’m the epitome of honesty and wisdom, except when I’m not.