[comp.lang.c] Unions

dan@hrc.UUCP (Dan Troxel VP) (10/20/88)

Except for the memory savings, what are Unions suited for?
-- 
Dan Troxel VP of Computer Operations @ 
Handwriting Research Corporation - 2821 E. Camelback Road Suite 600
Phoenix, AZ  85016       WK 1-602-957-8870        HM 1-602-435-1240
UUCP : asuvax!hrc!dan

gwyn@smoke.BRL.MIL (Doug Gwyn ) (10/20/88)

In article <322@hrc.UUCP> dan@hrc.UUCP (Dan Troxel VP) writes:
>Except for the memory savings, what are Unions suited for?

Structures containing unions can be used much like Pascal variant records.

kay@hjuxa.UUCP (KAY) (10/20/88)

In article <322@hrc.UUCP>, dan@hrc.UUCP (Dan Troxel VP) writes:
> 
> Except for the memory savings, what are Unions suited for?
> -- 
> Dan Troxel VP of Computer Operations @ 

Probably one of hundreds answering, but....

"Unions provide a way to manipulate different kinds of data in a single area
of storage, without embedding machine-dependent information in the program"
		-K&R, first edition, p138

Actually I usually use them _to_ embed machine _dependant_ information.
I have most often used unions for byte and word swapping when going from one
processor type to another; e.g. PDP to VAX, VAX to 8086, IBM (Serries 1) to
VAX, et cetera:
	union swap {
		short s_val;
		long l_val;
		char bytes[4];	/* see, very machine specific! */
	}

I've also used them to do initial processing on data that always had a
common first element to say what type of data the message contained. Most
recently to put varied information into a constant sized area as in the AT&T
COFF symbol table auxillary (debug) entries. Until you've tried this in
BLISS, you don't appreciate how complex this is.

Got to go.

	Paul S. Kay

pardo@june.cs.washington.edu (David Keppel) (10/20/88)

dan@hrc.UUCP (Dan Troxel VP) writes:
>Except for the memory savings, what are Unions suited for?

Well, I guess that they indicate something about the usage of the
fields in the union.  This is a programmer convenience rather than a
runtime convenience.

	    ;-D on  ( CFL -- C-free language )  Pardo
-- 
		    pardo@cs.washington.edu
    {rutgers,cornell,ucsd,ubc-cs,tektronix}!uw-beaver!june!pardo

rkl1@hound.UUCP (K.LAUX) (10/20/88)

In article <322@hrc.UUCP>, dan@hrc.UUCP (Dan Troxel VP) writes:
> 
> Except for the memory savings, what are Unions suited for?
> -- 
> Dan Troxel VP of Computer Operations @ 
> Handwriting Research Corporation - 2821 E. Camelback Road Suite 600
> Phoenix, AZ  85016       WK 1-602-957-8870        HM 1-602-435-1240
> UUCP : asuvax!hrc!dan


	The purpose of Unions is so that several different data types can
be stored in a common memory location (but you've already said that).  Of
course you can get into trouble if you have and int and a float in a union
and store a floating value there, then pull it out as an int :-).

	One use of unions is to have different pointer types declared in one and
then having the union as part of a structure.  Then you could use malloc and
cast the pointer returned to various types as needed.  This would allow for your
code to manipulate the structure with multiple types of pointers in it.

--rkl

cramer@optilink.UUCP (Clayton Cramer) (10/21/88)

In article <322@hrc.UUCP>, dan@hrc.UUCP (Dan Troxel VP) writes:
> 
> Except for the memory savings, what are Unions suited for?
> -- 
> Dan Troxel VP of Computer Operations @ 

They can be useful for showing that several different possible alternatives
are just that -- alternatives.  Consider:

        union uTag
            {
            int     CmdTblJumpIndex;
            PFI     FuncToExecute;
            char*   SystemCmdToRun;
            }   ActionToTake;

vs.

            int     CmdTblJumpIndex;
            PFI     FuncToExecute;
            char*   SystemCmdToRun;

The first example shows that all three are alternatives, and in fact,
if you tried to write code that used two of them at once, it wouldn't
work correctly.
        
-- 
Clayton E. Cramer
..!ames!pyramid!kontron!optilin!cramer

badri@valhalla.ee.rochester.edu (Badri Lokanathan) (10/21/88)

In article <322@hrc.UUCP>, dan@hrc.UUCP (Dan Troxel VP) writes:
> 
> Except for the memory savings, what are Unions suited for?

Here are two simple examples where I find unions to be very convenient:

(1) Consider an application that involves linked lists, except
    that the value field may have different items. Rather than write
    add/delete routines for each type of item, make the value field to
    be a union of the various types of values and write only one
    add/delete routine. This works best from the viewpoint of memory
    saving if the value field is of approximately same size (for
    instance, a pointer to another structure.)

(2) If you want to implement the adjacency list scheme for a graph from the
    cover of Aho, Hopcroft and Ullman's Design and analysis of algorithms,
    unions are great:

	    		--------------------------------------
	Vertex item  -->| Vertex attributes | ptr to edges   |
	    		--------------------------------------
	Edge item    -->| Edge attributes | ptr to next edge | 
	    		--------------------------------------

	Here one can union the attributes. For instance:

union Adjacency_list {
	struct {
		char name[8];		       	/* Name of vertex   */
		short low;                      /* Low point */
		union Adjacency_list *edges;    /* Ptr to edge list */
	} vert;

	struct {
		union Adjacency_list *v;	/* Other end of this edge */
		short low1;			/* First low point */ 
		short low2;			/* Second low point */ 
		short weight;			/* Weight of edge */
		union Adjacency_list *next;     /* Ptr to next edge */
	} edge;
};
-- 
"It's better to burn out               {) badri@valhalla.ee.rochester.edu
 Than it is to rust-                  //\\ {ames,cmcl2,columbia,cornell,
 But I'll corrode                    ///\\\ garp,harvard,ll-xn,rutgers}!
 Till I turn to dust."                _||_   rochester!ur-valhalla!badri

cik@l.cc.purdue.edu (Herman Rubin) (10/21/88)

In article <2699@hound.UUCP>, rkl1@hound.UUCP (K.LAUX) writes:
> In article <322@hrc.UUCP>, dan@hrc.UUCP (Dan Troxel VP) writes:
> > 
> > Except for the memory savings, what are Unions suited for?
> > -- 
> > Dan Troxel VP of Computer Operations @ 
> > Handwriting Research Corporation - 2821 E. Camelback Road Suite 600
> > Phoenix, AZ  85016       WK 1-602-957-8870        HM 1-602-435-1240
> > UUCP : asuvax!hrc!dan

Another use is so that the unnecessary restrictions of strong typing can
be overcome.  There are times when it is a good thing to use integer
operations on floating point numbers (caution: machine dependent).
An alternative would be to have a _use_ pseudooperation (distinct from
cast), but even with it, I would want unions.

It may also be desirable to have objects such as four bytes or two 16-bit
words treated as a 32-bit word for certain purposes.  I have treated two
32-bit words as a 64-bit word for shifting on a machine which could not
shift 32-bit words.  A programmer who has some understanding of the machine
can come up with many of these.

One complaint that I have about the C compilers I have used is that they
do not support register unions.
-- 
Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907
Phone: (317)494-6054
hrubin@l.cc.purdue.edu (Internet, bitnet, UUCP)

friedl@vsi.COM (Stephen J. Friedl) (10/21/88)

In article <322@hrc.UUCP>, dan@hrc.UUCP (Dan Troxel VP) writes:
> 
> Except for the memory savings, what are Unions suited for?

Collective bargaining.
-- 
Steve Friedl    V-Systems, Inc.  +1 714 545 6442    3B2-kind-of-guy
friedl@vsi.com     {backbones}!vsi.com!friedl    attmail!vsi!friedl
---------Nancy Reagan on the Three Stooges: "Just say Moe"---------

henry@utzoo.uucp (Henry Spencer) (10/21/88)

In article <322@hrc.UUCP> dan@hrc.UUCP (Dan Troxel VP) writes:
>Except for the memory savings, what are Unions suited for?

Type cheating.  (On a use-at-your-own risk basis, of course.)
-- 
The meek can have the Earth;    |    Henry Spencer at U of Toronto Zoology
the rest of us have other plans.|uunet!attcan!utzoo!henry henry@zoo.toronto.edu

maart@cs.vu.nl (Maarten Litmaath) (10/21/88)

\In article <322@hrc.UUCP>, dan@hrc.UUCP (Dan Troxel VP) writes:
\
\ Except for the memory savings, what are Unions suited for?

Beside reasons mentioned so-far, there's alignment:

	union	_u {
			int	i;
			char	buf[17];
		} u;

This construct will let you safely read an integer starting at &u.buf[0],
i.e. no bus error will occur.
K&R: a union can be thought of as a struct, all whose fields begin at offset 0.
-- 
Hippic sport:                         |Maarten Litmaath @ Free U Amsterdam:
             a contradiction in terms.|maart@cs.vu.nl, mcvax!botter!maart

cs78404@wright.EDU (Student of Dr. Sanders) (10/22/88)

in article <322@hrc.UUCP>, dan@hrc.UUCP (Dan Troxel VP) says:
> 
> 
> Except for the memory savings, what are Unions suited for?
>
Unions are used to logically group related data structures.

For example, if you have twelve structs with a queue in each, you can
group all of the queues together logically with a union statement.

chris@mimsy.UUCP (Chris Torek) (10/22/88)

In article <976@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) notes
that unions can be used to escape the type rules when necessary (glad
someone else said it so I did not have to :-) ), and adds:

>One complaint that I have about the C compilers I have used is that they
>do not support register unions.

Nor register structures, for that matter; this is silly.  The compiler
will return a four-byte integer in a register, so why will it not return
a four-byte structure in a register?

There *are* compilers that do it right.  (Does GCC?)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

pardo@june.cs.washington.edu (David Keppel) (10/22/88)

In article <14103@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>[ register unions ]
>There *are* compilers that do it right.  (Does GCC?)

Lint(1) complains about the construct "register union" when you try to
access a field of it.

Gcc (the GNU project C compiler) gets this right, however, even in the
case where you have (say) array components as part of the union:

    union u{
	int x;
	char y[2];
    };

	union u
    foo (x)
	int x;
    {
	register union u splat;

	splat.x = x + 2;
	(void)printf ("splat %d\n", splat.x);
	splat.y[0] = 'c';
	splat.y[1] = 'd';
	return splat;
    }

The resulting VAX code is:

    #NO_APP
    .text
	    .align 0
    LC0:
	    .ascii "splat %d\12\0"
	    .align 1
    .globl _foo
    _foo:
	    .word 0x40
	    addl3 4(ap),$2,r0		# put union in register
	    movl r0,r6			# save value of union
	    pushl r0
	    pushab LC0
	    calls $2,_printf
	    movb $99,r6			# splat.y[0] = 'c'
	    insv $100,$8,$8,r6		# splat.y[1] = 'd'
	    movl r6,r0
	    ret

Interesting note: gcc preserves the high-order bits of the union.
I believe that this behavior is not guaranteed either by K&R or by the
dpANS proposed standard.  (Anybody know?  Tell me, please?)

Note also that gcc puts the union in the register even if you don't
ask it to, and if you take the address of it it will spill the value
to the stack (rather than performing all operations on the stack).
The union return value is returned in a register, I believe that
there is a flag to force return it on the stack.

	;-D on  ( A Programmer's Union )  Pardo
-- 
		    pardo@cs.washington.edu
    {rutgers,cornell,ucsd,ubc-cs,tektronix}!uw-beaver!june!pardo

john13@garfield.MUN.EDU (John Russell) (10/22/88)

>In article <322@hrc.UUCP> dan@hrc.UUCP (Dan Troxel VP) writes:
>>Except for the memory savings, what are Unions suited for?

Although it might be considered under memory savings, another use is to
encode logically related but mutually exclusive pieces of information.
For example, expressing a point on the screen as either a video memory address
or an (x,y) pair. In this case it isn't the fact you can save a few
bits that's important, it's that a single object will always convey
the information regardless of how it's represented.

John
-- 
"The 68000 processor can't possibly handle a colour display. You must have a
 68020 system and not know it."
		-- Amiga and Atari ST owners shared a chuckle over this view
		   from sales *and* technical people at the local Apple dealer

gwyn@smoke.BRL.MIL (Doug Gwyn ) (10/23/88)

In article <976@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
>One complaint that I have about the C compilers I have used is that they
>do not support register unions.

Please explain how that would work.  Or else (preferably) stop complaining.

gwyn@smoke.BRL.MIL (Doug Gwyn ) (10/23/88)

In article <6176@june.cs.washington.edu> pardo@cs.washington.edu (David Keppel) writes:
>Interesting note: gcc preserves the high-order bits of the union.
>I believe that this behavior is not guaranteed either by K&R or by the
>dpANS proposed standard.  (Anybody know?  Tell me, please?)

Nothing is promised about other members of a union when one member is
modified, just as nothing is promised about the holes in a structure
or union.

cik@l.cc.purdue.edu (Herman Rubin) (10/23/88)

In article <8724@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes:
> In article <976@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
> >One complaint that I have about the C compilers I have used is that they
> >do not support register unions.
> 
> Please explain how that would work.  Or else (preferably) stop complaining.

Here is a very simple example.  BTW, I have seen C sources which use precisely
this construction.

union un {*int i; *float f;};

.....

register union un var1, var2;

Can anyone give me any conceivable reason why this union, whose size is
exactly one register on the machines I have tried it on, is not put into
an available register?  On one of the machines (Pyramid), local variables
were normally put into registers, but the compiler would not put the union
there.  I know this particular case can be done with casts, but other cases
cannot.
-- 
Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907
Phone: (317)494-6054
hrubin@l.cc.purdue.edu (Internet, bitnet, UUCP)

tim@crackle.amd.com (Tim Olson) (10/24/88)

In article <981@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
| Here is a very simple example.  BTW, I have seen C sources which use precisely
| this construction.
| 
| union un {*int i; *float f;};
| 
| .....
| 
| register union un var1, var2;
| 
| Can anyone give me any conceivable reason why this union, whose size is
| exactly one register on the machines I have tried it on, is not put into
| an available register?  On one of the machines (Pyramid), local variables
| were normally put into registers, but the compiler would not put the union
| there.  I know this particular case can be done with casts, but other cases
| cannot.

The MetaWare C compiler for the Am29000 does precisely what you want --
it keeps all register-sized variables in registers, as long as their
address isn't taken in the function.  This includes unions, structs, and
even arrays.  Aggregates such as structs are also passed as parameters
to functions in registers.



	-- Tim Olson
	Advanced Micro Devices
	(tim@crackle.amd.com)

terry@wsccs.UUCP (Every system needs one) (10/30/88)

In article <6142@june.cs.washington.edu>, pardo@june.cs.washington.edu (David Keppel) writes:
> dan@hrc.UUCP (Dan Troxel VP) writes:
> >Except for the memory savings, what are Unions suited for?
> 
> Well, I guess that they indicate something about the usage of the
> fields in the union.  This is a programmer convenience rather than a
> runtime convenience.

Packets.  It is nice to have a model which resembles reality.  The type field
would, of course, not be included within the union.

Namelists.	You can use symbol table information in a debugger in a way
that was not intended in the compiler.  Sharing common data structures is
desirable thing when writing a debugger.

Different reading and writing models for devices.  This can be used to speed
up disk I/O immensely.


| Terry Lambert           UUCP: ...{ decvax, uunet } ...utah-cs!century!terry |
| @ Century Software        OR: ...utah-cs!uplherc!sp7040!obie!wsccs!terry    |
| SLC, Utah                                                                   |
|                   These opinions are not my companies, but if you find them |
|                   useful, send a $20.00 donation to Brisbane Australia...   |
|                   'I have an eight user poetic liscence' - me               |

thomas@uplog.se (Thomas Hameenaho) (11/08/88)

In article <23341@amdcad.AMD.COM> tim@crackle.amd.com (Tim Olson) writes:
<example deleted>

>The MetaWare C compiler for the Am29000 does precisely what you want --
>it keeps all register-sized variables in registers, as long as their
>address isn't taken in the function.

So does gcc.
-- 
Real life:	Thomas Hameenaho		Email:	thomas@uplog.{se,uucp}
Snail mail:	TeleLOGIC Uppsala AB		Phone:	+46 18 189406
		Box 1218			Fax:	+46 18 132039
		S - 751 42 Uppsala, Sweden