Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!mnetor!uunet!husc6!cmcl2!brl-adm!brl-smoke!gwyn
From: gwyn@brl-smoke.ARPA (Doug Gwyn )
Newsgroups: comp.lang.c
Subject: Re: How to discriminate the structures?
Message-ID: <6779@brl-smoke.ARPA>
Date: Thu, 3-Dec-87 01:15:27 EST
Article-I.D.: brl-smok.6779
Posted: Thu Dec  3 01:15:27 1987
Date-Received: Sun, 6-Dec-87 09:32:45 EST
References: <420@slb-sdr.UUCP>
Reply-To: gwyn@brl.arpa (Doug Gwyn (VLD/VMB) )
Organization: Ballistic Research Lab (BRL), APG, MD.
Lines: 53
Keywords: structure, typeof()

In article <420@slb-sdr.UUCP> saito@slb-sdr.UUCP (Naoki Saito) writes:
>foo(point)
>     caddr_t *point; /* In fact, I don't know how to declare point here. */
>		     /* caddr_t is "character address type" used in Sun. */
>{
>  if (typeof(*point) == POINT)
>    { do something...}
>  else if (typeof(*point) == POINTR)
>    { do something...}
>}

What the above wants is impossible in principle, unless some sort of
"dope vector" is used for parameter passing.  Because dope vectors add
non-negligible overhead, language implementors normally do not resort
to them unless they're forced to.  C is deliberately designed so as
not to require such overhead on most architectures.

There are two alternative approaches; first, with minimal changes to
your example:

	/* ... typedefs unchanged */

	foo(enum {POINT_T, POINTR_T} type, void *point)
	{
		if (type == POINT_T)
			{/* use ((POINT *)point) */}
		else if (type == POINTR_T)
			{/* use ((POINTR *)point) */}
	}

or, what I would actually recommend:

	typedef struct {
		enum {POINT_T, POINTR_T} type;
		union {
			struct {
				float x;
				float y;
			} cartesian;
			struct {
				float r;
				float theta;
			} polar;
		} u;
	} coords;

	foo(coords *point)
	{
		if (point->type == POINT_T)
			{/* use point->u.cartesian.x etc. */}
		else if (point->type == POINTR_T)
			{/* use point->u.polar.r etc. */}
	}