TheJach.com

Jach's personal blog

(Largely containing a mind-dump to myselves: past, present, and future)
Current favorite quote: "Supposedly smart people are weirdly ignorant of Bayes' Rule." William B Vogt, 2010

C does support encapsulation!

Relating to my previous post, I'd just like to mention that C supports encapsulation, and in my opinion much better than C++. It's done using Opaque Pointers.

Here's some code:


#######blah.h########
#IFNDEF H_BLAH
#DEFINE H_BLAH
typedef struct Blah* Blah_handle;
Blah_handle create_blah(void);
void destroy_blah(Blah_handle);
void print_blah(Blah_handle);
#ENDIF



#######blah.c########
#include <stdlib.h>
#include <stdio.h>
#include "blah.h"
struct Blah {
int x;
int y;
int z;
int q;
};


Blah_handle create_blah(void) {
struct Blah* new_b = malloc(sizeof(struct Blah));
new_b->x = 1;
new_b->y = 2;
new_b->z = 3;
new_b->q = 4;
return new_b;
}

void destroy_blah(Blah_handle b) {
free(b);
}

void print_blah(Blah_handle b) {
printf("%d %d %d %d\n", b->x, b->y, b->z, b->q);
}

#######client.c#######
#include <stdio.h>
#include "blah.h"

int main(void) {
Blah_handle b = create_blah();
print_blah(b);
printf("%ld\n", sizeof(b));
destroy_blah(b);
return 0;
}


Why is this better? sizeof(b) will return "8" on my 64-bit machine, and "4" on a 32-bit machine, because it only knows it's a pointer. "I know," you say, "I'll try dereferencing b to modify it!". Woops, that's a compile-time error: "dereferencing pointer to incomplete type". "I know," you say, "I'll modify the .h file and re-typedef the handler to not be a pointer!" Well, aside from the other problems, the main one you'll get is this:


error: variable 'b' has initializer but incomplete type
error: storage size of 'b' isn't known


What does this mean? It means that the C compiler has compile-time encapsulation as well as runtime encapsulation, that can't be beaten quite as trivially as C++... You can still do it, though, but it requires more knowledge than what you have from compile or runtime, it requires you know exactly what's in the .c file and how it's implemented. This will work as expected:

  *(int*)((char*)b + sizeof(int)) = 10;


and change b->y to 10. So neither C nor C++ support real encapsulation, but C feels a lot closer to that goal than C++ does. Not to mention C doesn't have to recompile "client.c" if the implementation of "blah.c" changes! In C++, if you change a private member, everything that references the class must be recompiled.


Posted on 2010-10-10 by Jach

Tags: c, programming

Permalink: https://www.thejach.com/view/id/131

Trackback URL: https://www.thejach.com/view/2010/10/c_does_support_encapsulation

Back to the top

Back to the first comment

Comment using the form below

(Only if you want to be notified of further responses, never displayed.)

Your Comment:

LaTeX allowed in comments, use $$\$\$...\$\$$$ to wrap inline and $$[math]...[/math]$$ to wrap blocks.