I've seen both of the following two styles of declaring opaque types in C APIs. Is there any clear advantage to using one style over the other?
Option 1
// foo.h
typedef struct foo * fooRef;
void doStuff(fooRef f);
// foo.c
struct foo {
int x;
int y;
};
Option 2
// foo.h
typedef struct _foo foo;
void doStuff(foo *f);
// foo.c
struct _foo {
int x;
int y;
};
My vote is for the third option that mouviciel posted then deleted:
I have seen a third way:
// foo.h
struct foo;
void doStuff(struct foo *f);
// foo.c
struct foo {
int x;
int y;
};
If you really can't stand typing the struct
keyword, typedef struct foo foo;
(note: get rid of the useless and problematic underscore) is acceptable. But whatever you do, never use typedef
to define names for pointer types. It hides the extremely important piece of information that variables of this type reference an object which could be modified whenever you pass them to functions, and it makes dealing with differently-qualified (for instance, const
-qualified) versions of the pointer a major pain.
bar(const fooRef)
declares an immutable address as argument. bar(const foo *)
declares an address of an immutable foo as argument.
For this reason, I tend to prefer option 2. I.e., the presented interface type is one where cv-ness can be specified at each level of indirection. Of course one can sidestep the option 1 library writer and just use foo
, opening yourself to all sorts of horror when the library writer changes the implementation. (I.e., the option 1 library writer only perceives that fooRef
is part of the invariant interface and that foo
can come, go, be altered, whatever. The option 2 library writer perceives that foo
is part of the invariant interface.)
I'm more surprised that no one's suggested combined typedef/struct constructions.
typedef struct { ... } foo;