[comp.lang.c] casting to/from union types

rhg@cpsolv.CPS.COM (Richard H. Gumpertz) (05/31/90)

It is possible to effectively cast a union type to one of its component types
by appending ".X" where X is the name of the component.  Unfortunately, there
is no way to do the reverse cast; instead one has to allocate a temporary and
then assign to the temporary.  For example, to pass an int I to a function
that takes a union argument, one might use:
	extern int I;
	typedef union { int I; float F; } U;
	extern foo(int which, U x);
	U tempU;

	foo(1, (tempU.I = I, tempU));

A much cleaner syntax (to read) might be:
	foo(1, (U)I);

A problem arises is if one wants to pass a constant: the type of constants is
non-intuitive.  For example, if we change the above typdef to
	typedef union { int I; float F; char C; } U;
and then call
	foo(3, (U)'X');
then should the 'X' be effectively assigned to the I field or the C field?

I suppose we could disambiguate between th I and C fields using a whole new
kludge like
	foo(3, (U.C)'X');
but that seems ugly.

Does anybody have a better idea as to how one might allow casting arguments
to functions that accept union types without having to allocate a temporary?
The details are non-obvious.  Could the people on the net invent an extension
that would read cleanly, maybe get some trial use, and perhaps even be
proposed for inclusion for C-95 or whatever?

Please reply via e-mail and I will summarize.

-- 
  ==========================================================================
  | Richard H. Gumpertz    rhg@CPS.COM    (913) 642-1777 or (816) 891-3561 |
  | Computer Problem Solving, 8905 Mohawk Lane, Leawood, Kansas 66206-1749 |
  ==========================================================================

steve@taumet.COM (Stephen Clamage) (06/01/90)

In article <523@cpsolv.CPS.COM> rhg@cpsolv.uucp (Richard H. Gumpertz) writes:
[ to cast from a component type to the union type ... ]
>one has to allocate a temporary and then assign to the temporary.
>...
>Does anybody have a better idea as to how one might allow casting arguments
>to functions that accept union types without having to allocate a temporary?

You can already do this in C++.  You define a conversion function as part
of the union.  You could get the same effect in C by writing a conversion
function:
	union U { int i; /* etc */ };
	union U convert_int_to_U(int i)
	{
		union U u;
		u.i = i;
		return u;
	}

It seems unnecessary to invent an extension to C to accomodate what must
be a very unusual operation.  If you don't explicitly declare a temp
and assign to it, the compiler has to do it for you, and the generated
code comes out the same.  (If you pass an int, but the largest member of
the union is bigger than that, not enough will have been passed as the
parameter.)  So the most you save is a line of source code.

But maybe what you really want to do could be accomplished by writing a
variadic function instead of one taking a union:

	enum WhatKind { intkind, doublekind, longkind, /* etc */ };
	SomeType funny_func(WhatKind, ...);
	void foo()
	{
		SomeType s = funny_func(doublekind, 2.0);
	}
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

brnstnd@stealth.acf.nyu.edu (06/06/90)

In article <235@taumet.COM> steve@taumet.UUCP (Stephen Clamage) writes:
  [ on casting from a component type to the union type ]
> It seems unnecessary to invent an extension to C to accomodate what must
> be a very unusual operation.

There's at least one ``usual'' example of essentially the same problem,
namely in BSD Internet socket programming: struct in_addr has just a
single component, namely u_long s_addr. In the one case where I ever
used one value as both those types, I kept just the struct around, and
referred to its s_addr component when necessary. This always works.

---Dan