[comp.lang.c] Using data types before they are declared.

awehrmann@watcgl.waterloo.edu (August Wehrmann) (06/13/89)

I have a question: 

Is it possible, (and if so, how?), to use a data type in a declaration
of say, a union, that has not yet been declared?

Here is an example of what I'm talking about.

union Fred {              <--------
	int 	Number;            |
	element	Node;     <...........
};                                 | .
                                   | .
typedef struct {                   | .
	int	Info;              | .
	Fred	Name;     <--------  .
} *element;               <...........


Please e-mail any replies. Quick references to Kernighan and Ritchie would also
be appreciated.

Thanks in advance.

-- 
===============================================================================
 August Wehrmann, awehrmann@watcgl{.waterloo.edu, UWaterloo.ca} 
 Computer Graphics Lab, Department of Computer Science, University of Waterloo
===============================================================================

db2@pbinfo.UUCP (Vorl. Informationssysteme) (06/14/89)

In article <10268@watcgl.waterloo.edu> awehrmann@watcgl.waterloo.edu (August Wehrmann) writes:
>I have a question: 
>
>Is it possible, (and if so, how?), to use a data type in a declaration
>of say, a union, that has not yet been declared?
>
>[Example omitted]
>
>union Fred {              <--------
>	int 	Number;            |
>	element	Node;     <...........
>};                                 | .
>                                   | .
>typedef struct {                   | .
>	int	Info;              | .
>	Fred	Name;     <--------  .
>} *element;               <...........
>
>Thanks in advance.
>

I would use the following:

union Fred {
	int		Number;
	struct _el_str	*Node;
};

struct _el_str {
	int	Info;
	Fred	Name;
};
typedef	struct _el_str	*element;

I am practising this in my own programs very often.

	D. Aedal
	YACSS (Yet Another CS Student)

chris@mimsy.UUCP (Chris Torek) (06/19/89)

In article <548@corona.pb> db2@pbinfo.UUCP (Vorl. Informationssysteme)
suggests trying the following code:
>union Fred {
>	int		Number;
>	struct _el_str	*Node;
>};
>
>struct _el_str {
>	int	Info;
>	Fred	Name;
>};
>typedef	struct _el_str	*element;
>
>I am practising this in my own programs very often.

I doubt it: as written, it will not compile.  (It will in C++, however.)

The best approach is to ignore `typedef' completely, give all
structures and unions tags, and add typedefs afterward if you
wish.  Thus:

	union Fred {
		int	Number;
		struct	_el_str *Node;
	};

	struct _el_str {
		int	Info;
		union	Fred Name;
	};

(The difference between this and the first 9 lines of code quoted
above is the addition of one `union' keyword.)  Then, if necessary:

	typedef union Fred {
		int	Number;
		struct	_el_str *Node;	/* no synonyms available */
	} Fred;
	/* `Fred' is now a synonym for `union Fred' */

	typedef struct _el_str {
		int	Info;
		union	Fred Name;	/* this can now be abbreviated */
	} *element;
	/* `element' is now a synonym for `struct _el_str *' */

Other approaches are possible, but this one always works: Avoid the
abbreviation until it has been defined, and always use a structure
or union tag so that there *is* an unabbreviated form.  At worst, you
will invent some tags you never use.

Incidentally, I happen to like the practise of naming structure and
union elements in a `type-describing' manner:

	struct glumph {
		char	*g_name;	/* name of this glumph */
		int	g_mass;		/* mass of this glumph, in kg */
		short	g_halflife;	/* biodegredation halflife, years */
		short	g_cost;		/* price in cents per kg */
	};

If I then spot a line like

	p->g_mass

somewhere, I have a clue (the `g_' element prefix) that `p' is an
object of type `pointer to struct glumph'.

(This practise arose from pre-V7 C's approach of putting all structure
elements/offsets in a single global table, making unions unnecessary,
but forcing prefixes to guarantee uniqueness, and weakening type-checking.
The prefixes turned out to be convenient, and were included in new
structures in V7 and BSD.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

davidsen@sungod.crd.ge.com (William Davidsen) (06/20/89)

In article <18137@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:

| The best approach is to ignore `typedef' completely, give all
| structures and unions tags, and add typedefs afterward if you
| wish.  Thus:

  definitions are sometimes useful to reduce typing as well. For
instance in a simple linked list declaration:

	#define D_litem struct _litem

	D_litem {
	  int xa[4], xb[4];
	  D_litem *fwd, *back;
	  float lo_lim, hi_lim;
	  D_litem *execptions;
	};
	typedef D_litem litem

  This is a real typing saver when a number of structs include one
another or pointers to one another.
	bill davidsen		(davidsen@crdos1.crd.GE.COM)
  {uunet | philabs}!crdgw1!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me