tags:

views:

183

answers:

3

I've seen the concept of 'opaque types' thrown around a bit but I really haven't found a succinct answer as to what defines an opaque type in C and more importantly what problems they allow us to solve with their existence. Thanks

+3  A: 

In my understanding, opaque types are those which allow you to hold a handle (i.e., a pointer) to an structure, but not modify or view its contents directly (if you are allowed to at all, you do so through helper functions which understand the internal structure).

Opaque types are, in part, a way to make C more object-oriented. They allow encapsulation, so that the internal details of a type can change--or be implemented differently in different platforms/situations--without the code that uses it having to change.

Tim Yates
Quibble: this idiom is *only* about encapsulation. Encapsulation is necessary to object-orientation, but it is the smallest piece of it.
dmckee
True, it takes a lot more than this for anything nearly object-oriented. Still, it is the one part of object-oriented design that I find I am *always* missing when I write in C. Plus, if you *were* to try to emulate inheritance and polymorphism in C (more work than it is worth), you would almost certainly need to start with opaque types.
Tim Yates
Remember that c and the culture that it engendered date from a time when object orientation was a rare and still rather experimental thing. Procedural and functional programmers of the time concentrated of encapsulation as *the* means of controlling inter-connectivity and unnecessary complexity. Talking about opaque types in c as a kind of crippled object is pushing a foreign POV onto the language. – dmckee 10 mins ago
dmckee
+1  A: 

An opaque type is a type which is exposed in APIs via a pointer but never concretely defined.

JaredPar
+6  A: 

It is the most generally used for library purpose. Since the implementation is hidden, you can modify the library without recompiling any program which depend on it (if the interface is respected)

eg: version 1:

// header file
struct s;

int s_init(struct s **x);
int s_f(struct s *x);
int s_g(struct s *x);

// implementation
struct s { int x; }

int s_init(struct s **x) { *x = malloc(...); }
int s_f(..) { ... }
int s_g(..) { ... }

version 2

// header file
struct s;

int s_init(struct s **x);
int s_f(struct s *x);
int s_g(struct s *x);

// implementation
struct s { int y; int x; }

int s_init(struct s **x) { *x = malloc(...); }
int s_f(..) { ... }
int s_g(..) { ... }

From your program side, nothing changed! and as said previously, no need to recompile every single program which rely on it.

Phong
I am assuming that the '//implementation' portions are not apart of the same '//header file' and are what go in the libraries? Also, it seems like you declared `struct s` in the header but never defined it until the implementation. I recently read a great post on `extern` variables in C http://stackoverflow.com/questions/1433204/what-are-extern-variables-in-c The concepts seem strikingly similar, should not `struct s` be declared as `extern struct s` in your sample code?
SiegeX
using extern for variable is generally used to declare global variable (which is absolutely not related to our case). Here the instruction struct s; is here to indicate to the compilator a type named struct s exist. Since all API in the header file ONLY use pointer to this strucure. It does not need to know the structure size but the size of the pointer of structure (which is define by the compiler). To simplify, it allows the program use a object by using its address (the pointer to the structure)
Phong