[This is extracted from a mail message I sent on 1997-09-23, to someone who asked for an example.]

From: scs@eskimo.com (Steve Summit)
Subject: Re: ADT??
Date: Tue, 23 Sep 1997 18:21:38 -0700 (PDT)
Message-Id: <199709240121.SAA03216@mail.eskimo.com>

...you might have, in adt.h, the declarations:

	extern struct adt *newadt(void);
	extern int processadt(struct adt *);
	extern void freeadt(struct adt *);

Then a client could do:

	#include "adt.h"
	struct adt *theadt = newadt();
	processadt(theadt);
	freeadt(theadt);

The actual implementation of the ADT would start out like this:

	#include "adt.h"
	struct adt
		{
		/* actual structure definition */
		};

	struct adt *
	newadt(void)
	{
	...

Or, if the ADT's implementation comprises several source files, you could put the structure definition in, say, adtinternals.h:

	struct adt
		{
		/* actual structure definition */
		};

Then, include both adt.h and adtinternals.h in each source file implementing the ADT:

	#include "adt.h"
	#include "adtinternals.h"

	struct adt *
	newadt(void)
	{
	...

Occasionally, I find it useful to centralize all declarations concerning an ADT into one header file ("adt.h", in the continuing example), in which case I do it like this:

	#ifdef ADT_INTERNALS
	struct adt
		{
		/* actual structure definition */
		};

	#endif

	extern struct adt *newadt(void);
	extern int processadt(struct adt *);
	extern void freeadt(struct adt *);

Then I define ADT_INTERNALS in each source file implementing the ADT, just before including adt.h:

	#define ADT_INTERNALS
	#include "adt.h"

	struct adt *
	newadt(void)
	{
	...

This is obviously a weaker form of information hiding, because it's easier for a client to ``cheat'' and peek at the type's implementation.

Finally, when you use the first form, with the incomplete structure type, it's often useful to place an incomplete structure declaration in the public header file:

	struct adt;
	extern struct adt *newadt(void);
	extern int processadt(struct adt *);
	extern void freeadt(struct adt *);

This prevents certain compiler warnings, and averts a couple of other obscure possible problems.