[comp.lang.c] Circular references in declerations

grant@cft.philips.nl (Joe Grant) (02/27/90)

Calling all C gurus,

	A colleague of mine has run into the following problem.
	He needs to use the following declarations:

	typedef union {
			int *a;
			float *e;
			X *x;
		} Y

	typedef struct {
			int *d;
			.
			.
			.
			Y *y;
		}

	and neither of us are sure how the circular references of Y and X 
	will be interpreted. To the best of my knowledge C promises nothing 
	with regard to circular references, however I'm no guru so I told him
	that I'd see what the net thinks of the problem. The code needs to
	be portable, and I have a funny feeling that this may be compiler 
	dependent, in which case another solution will need to be found.
	
	If any of you know what should happen, or have any ideas or comments 
	I'd appreciate hearing from you

	Joe Grant


-- 
Joe Grant,                       Telex     : 35000 phtc nl/nlmtfarr
Philips B.V., Building HKJ-p833, Telefax   : (31.40.7)37222
P.O. Box 218, 5600 MD Eindhoven, E-mail    : grant@nlccl.cft.philips.nl
The Netherlands.                 Telephone : (31.40.7)34382

martin@mwtech.UUCP (Martin Weitzel) (02/28/90)

In article <973@philtis.cft.philips.nl> grant@cft.philips.nl (Joe Grant) writes:
>
>
>Calling all C gurus,
>
>	A colleague of mine has run into the following problem.
>	He needs to use the following declarations:
>
>	typedef union {
>			int *a;
>			float *e;
>			X *x;
>		} Y
>
>	typedef struct {
>			int *d;
>			.
>			.
>			.
>			Y *y;
>		}
		  X <---- missing here??

I assume the missing X, otherwise your question would not make sense
to me.

This particluar piece of code should *not* compile (at least not with
an ANSI-Compiler), as type X is unknown in the typedef for Y. If you
need circular dependencies, you must write this as follows:

typedef union uy { ..... ; struct sx *x; ..... } Y;
typedef struct sx { ..... ; union uy *y; ..... } X;

In the second line, I could have used 'Y' in place of 'union uy'
(and hence ommit the union-tag 'uy' in the first typedef), but in
the first typedef the use of 'struct sx *' is essential: A C-Compiler
will accept this kind of declaration, even if it does not know,
what a 'struct sx' will be at this time. Most compilers will *not*
accept a type (and hence a pointer to a type) in this situation,
if they do not know the type allready.

By tradition (%), name spaces for struct- and union-tags (uy, sx)
are separated from the name space for typedef-s (X, Y), so you
could in fact write.

typedef union Y { ..... ; struct X *x; ..... } Y;
typedef struct X { ..... ; union Y *y; ..... } X;

and of course could change the second line to

typedef struct X { ..... ; Y *y; ..... } X;

I don't know, if I should recommend to choose the same name
as struct/union-tag *and* typedef-d name. If you fully understand
the background, it saves remembering 'which is which', but for
the 'non-gurus' it might obscure the facts.

(%): C++ breaks with this tradition: A struct- or union-tag is
*automatically* a type name.
-- 
Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83

karl@haddock.ima.isc.com (Karl Heuer) (03/01/90)

In article <677@mwtech.UUCP> martin@mwtech.UUCP (Martin Weitzel) writes:
>By tradition (%), name spaces for struct- and union-tags (uy, sx)
>are separated from the name space for typedef-s (X, Y), so you
>could in fact write.
>	typedef union Y { ..... ; struct X *x; ..... } Y;
>	typedef struct X { ..... ; union Y *y; ..... } X;
>I don't know, if I should recommend to choose the same name
>as struct/union-tag *and* typedef-d name. If you fully understand
>the background, it saves remembering 'which is which', but for
>the 'non-gurus' it might obscure the facts.

>(%): C++ breaks with this tradition: A struct- or union-tag is
>*automatically* a type name.

It is for this reason that I *always* use the same name for the tag and the
typedef: it makes it more compatible with C++ usage.  If I ever want to
convert the declarations to C++, all I have to do is remove the explicit
typedef, since C++ provides it automatically.  And since it has been suggested
that C-2001 might be a standardization of C++ rather than C (though I hope
not), it seems useful to keep the code "close" to C++ when the cost is small.

Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint