In article <ba****************@tematic.com>
Kevin Bracey <ke**********@tematic.com> wrote:
... [using] a typedef hides the fact the handle is a struct from the
basic API. One might want (for whatever reason) to change the handle
from an int to a structure or vice-versa.
Sure -- but then one could just define a struct containing a single
"int".
Always just use "struct"; it is C's way of defining abstract data
types. :-)
I am "only almost kidding" about "always", too. Note that using a
struct to hold a single scalar variable gives you type-safety:
struct temperature { double val; };
struct pressure { double val; };
Now it is impossible to accidentally pass a "temperature" to a
function requiring a "pressure". You can add a typedef if you
really want:
#ifdef USE_TYPEDEFS
typedef struct temperature Temperature;
typedef struct pressure Pressure;
typedef struct counter Counter;
#endif
struct temperature; /* opaque */
struct pressure; /* opaque */
struct counter { int val; }; /* exposed */
If you make the handle an int, you are stuck. If you make it a
typedef and make the typedef an int and someone uses an int, you
are *still* stuck:
/* remove previous typedef and struct */
typedef int Counter;
extern Counter add(Counter previous, int offset);
...
/* bad programmer, using int instead of the typeef-name: */
void f(void) {
int x;
...
x = add(x, 3); /* this code compiles just fine */
...
}
but if you use a struct -- whether opaque or exposed -- even the
bad programmer has to use the name you gave it:
/* put back typedef and struct */
/* bad programmer attempts to use int instead of the typedef-name: */
void f(void) {
int x;
...
x = add(x, 3); /* error: function add() requires a
struct counter and returns a struct counter,
so this code does not compile */
...
}
Of course, if you always use struct, the typedef is unnecessary. Just
think of the word "struct" as meaning "type":
#define type struct
type foo; /* declare type foo to exist */
type bar; /* declare type bar to exist */
static type foo x = FOO_INITIALIZER; /* make x a foo */
extern type bar y; /* declare y as a bar, defined elsewhere */
and you have a language with an obvious user-defined abstract data
type mechanism. Take out the single "#define" and you still have
that language -- it is called "C". :-) (Of course, to get everything
to work right, you need C99 with its compound-literals.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it
http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.