[comp.lang.c] Need help with union trick: summary of replies

jet@karazm.math.uh.edu ("J. Eric Townsend") (01/05/91)

I received many replies, some using #defines, others requiring other
changes.  I think the following message best summaraizes the answers that
work the best.

|From: timr@gssc.gss.com (Tim Roberts)
|
|I can think of two ways to solve your array aliasing problem.
|
|1. Ugly Union or Unnamed Structure.
|
|  typedef union pointstruct {
|      struct {
|	  double x, y, z;
|      } p;
|      double foo [3];
|  } Point;
|
|  Point a;
|
|Then  a.p.y == a.foo[1]  .  This is ugly because of the extra name required
|(that is, the "p").  However, this problem is solved in ANSI C by "anonymous
|structures", so if you're using ANSI C you can say:
|
|  typedef union pointstruct {
|      struct {
|	  double x, y, z;
|      };
|      double foo [3];
|  } Point;
|
|  Point a;
|
|Then  a.y == a.foo[1].  This is the best solution, if you have an ANSI 
|compiler.
|
|2. Raw Cast.
|
|typedef struct pointstruct {
|    double x, y, z;
|} Point;
|
|Point a;
|
|Now you can cast a pointer to a into a pointer to double and say something like:
|
|    a.y == ((double *)&a)[0]
|
|Hope this helps.
|-- 
|timr@gssc.gss.com	Tim N Roberts, CCP	Graphic Software Systems
|						Beaverton, OR
--
J. Eric Townsend     Internet: jet@uh.edu    Bitnet: jet@UHOU
Systems Mangler - UH Dept. of Mathematics - (713) 749-2120
"I don't know that atheists should be considered citizens ... or patriots.
This is `one nation under God'." -- President George Bush to an AA reporter.

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (01/05/91)

In article <1991Jan4.192645.7094@lavaca.uh.edu> jet@karazm.math.uh.edu ("J. Eric Townsend") writes:
> I received many replies, some using #defines, others requiring other
> changes.  I think the following message best summaraizes the answers that
> work the best.

The #define answers are the only safe ones so far. I wouldn't recommend
any of the others for anything you're planning to use on several
machines.

  [ ANSI anonymous structures: ]
> |  typedef union pointstruct {
> |      struct {
> |	  double x, y, z;
> |      };
> |      double foo [3];
> |  } Point;

This is not guaranteed to work because the structure elements might not
be contiguous, or even in order.

The right solution for a language designer is context definitions:

  typedef struct pointstruct
   {
    double foo[3];
    define x foo[0];
    define y foo[1];
    define z foo[2];
   }
  Point;

This would solve the same problems as ANSI anonymous structures but
would be a lot safer for unions.

---Dan

chris@mimsy.umd.edu (Chris Torek) (01/07/91)

In at least two articles at least two people write about

>ANSI anonymous structures

but X3.159-1989 does not have what these people mean.

The idea, which is supported by a number of `C-like' compilers, is to
allow union (and structure) definitions of the form

	struct value {
		enum { integer, floating } v_kind;
		union {
			int	v_integer;	/* value if integer */
			float	v_floating;	/* value if floating */
		};
	} v;

after which references of the form `v.v_integer' would be allowed.
Although this is useful, it is not part of `ANSI C'.  Some people use
workarounds that look like:

	struct value {
		enum { integer, floating } v_kind;
		union {
			int	vu_integer;
			float	vu_floating;
		} v_un;
	#define	v_integer	v_un.vu_integer
	#define	v_floating	v_un.vu_floating
	} v;

which causes a reference of the form `v.v_integer' to expand to one
of the form `v.v_un.vu_integer'.  Other people type in the extra `un.vu_'
every time (to emphasize the union).
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris

timr@gssc.UUCP (Tim Roberts) (01/08/91)

In article <28949@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes:
>In at least two articles at least two people write about
>
>>ANSI anonymous structures
>
>but X3.159-1989 does not have what these people mean.

My apologies.  How ethnocentric of me.  I do not know how I acquired this false
belief.  Upon further review, I discover that Microsoft C 6.0 does, in fact,
include this in their "extensions to the C language" section.

Thanks for the gentle correction.
-- 
timr@gssc.gss.com	Tim N Roberts, CCP	Graphic Software Systems
						Beaverton, OR

Zen Master to hot dog vendor:  "Make me one with everything."

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (01/08/91)

In article <6497@gssc.UUCP> timr@gssc.UUCP (Tim Roberts) writes:
> In article <28949@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes:
> >In at least two articles at least two people write about
> >>ANSI anonymous structures
> >but X3.159-1989 does not have what these people mean.
> My apologies.  How ethnocentric of me. 

Oops, me too.

I dunno nuthin' 'bout no ANSI. I'ze just a po-uh C programm-uh. :-)

Anyway... Does anyone see any correct solutions to this problem that
don't involve the preprocessor?

---Dan

dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (01/12/91)

I sort of like calling the union substructure by tiny names like x, y,
z etc.  Then references become struct_name.x.field_name, and the ".x."
is almost not noticeable.  The idea is to use a small meaningless name
(sort of using i, j, k as loop counters) so the meaningfullness (to
coin a noun) lies entirely in the name of the structure and the name of
the field.
--
History never         |   Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com>
becomes obsolete.     |   UUCP:  oliveb!cirrusl!dhesi

gceych@juliet.caltech.edu (Eychaner, Glenn C.) (01/13/91)

dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes...
>I sort of like calling the union substructure by tiny names like x, y,
>z etc.  Then references become struct_name.x.field_name, and the ".x."
>is almost not noticeable.  The idea is to use a small meaningless name
>(sort of using i, j, k as loop counters) so the meaningfullness (to
>coin a noun) lies entirely in the name of the structure and the name of
>the field.
>--
Me (in VaxC, I don't know if others support it) use variant_structures and
variant_unions. Example:

struct {
    variant_union {
	unsigned char ch;
	variant_struct {
	    unsigned one : 1;
	    unsigned two : 1;
	    ...
	    unsigned eig : 1;
	} superfluous;
    } superfluous2;
    int i, j, k, x, y, z;
} mystructure;

So you can reference the first bit of ch as mystructure.one, the second as
mystructure.two, ch as mystructure.ch, i as mystructure.i, etc.  All the
variables must have different names, BTW.  I use this for storing bit flags
to a file as a char or int (to avoid huge scanf statements and files full
of 1's & 0's).

Glenn C. Eychaner | "We demand rigidly defined areas of doubt and uncertainty."
40386 N. Shore Ln `-----.                                             -D. Adams
Big Bear City, CA 92314 `-----------------------. !**** G O  N I N E R S ****!
Eychaner%SunCub.Caltech.edu@Xhmeia.Caltech.edu -|- Big Bear Solar Observatory

gwyn@smoke.brl.mil (Doug Gwyn) (01/13/91)

In article <1991Jan12.190021.16071@nntp-server.caltech.edu> gceych@juliet.caltech.edu writes:
- struct {
-     variant_union {
- 	unsigned char ch;
- 	variant_struct {
- 	    unsigned one : 1;
- 	    unsigned two : 1;
- 	    ...
- 	    unsigned eig : 1;
- 	} superfluous;
-     } superfluous2;
-     int i, j, k, x, y, z;
- } mystructure;

Oh, gross.  If you use this highly nonstandard VMS C extension then
you'll have to overhaul your code when you port it to a different
environment.  It is much better to simply not use such unnecessary
vendor-specific extensions in the first place.

gceych@juliet.caltech.edu (Eychaner, Glenn C.) (01/13/91)

In article <14836@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes...
>In article <1991Jan12.190021.16071@nntp-server.caltech.edu> gceych@juliet.caltech.edu writes:
>- struct {
>-     variant_union {
>- 	unsigned char ch;
>- 	variant_struct {
>- 	    unsigned one : 1;
>- 	    unsigned two : 1;
>- 	    ...
>- 	    unsigned eig : 1;
>- 	} superfluous;
>-     } superfluous2;
>-     int i, j, k, x, y, z;
>- } mystructure;
> 
>Oh, gross.  If you use this highly nonstandard VMS C extension then
>you'll have to overhaul your code when you port it to a different
>environment.  It is much better to simply not use such unnecessary
>vendor-specific extensions in the first place.

The piece of code of which this is a small part contains so many system calls,
kludges, etc. that portability is not a major concern.  In fact, it was written
for a VAX station bought to eventually replace an 11/44.  At that rate of
replacement, the language will be obsolete before the code is. (The programs on
the 11/44 were written in an early Fortran.  Gross.  Which is just what they'll
think of VaxC by the time the programming needs to be ported.)

Besides, I happen to LIKE this particular construct for nested structures and
unions (as an option).  I hate remembering the names of all the intermediates.
Especially when the variables are all going to have different names anyway.

Direct flames to bit.bucket, please.

Glenn C. Eychaner | "We demand rigidly defined areas of doubt and uncertainty."
40386 N. Shore Ln `-----.                                             -D. Adams
Big Bear City, CA 92314 `-----------------------. !**** G O  N I N E R S ****!
Eychaner%SunCub.Caltech.edu@Xhmeia.Caltech.edu -|- Big Bear Solar Observatory

bengsig@oracle.nl (Bjorn Engsig) (01/14/91)

In article <1991Jan12.190021.16071@nntp-server.caltech.edu> gceych@juliet.caltech.edu writes:
|
|Besides, I happen to LIKE this particular construct for nested structures and
|unions (as an option).  I hate remembering the names of all the intermediates.
There is another wellknown trick for this, where you use dummy names for the
union inside the struct and union members and then

#define nice_name dummy_union_name.dummy_nice_name

so you can write mystruct.nice_name and really make your compiler see
mystruct.dummy_union_name.dummy_nice_name
-- 
Bjorn Engsig,         E-mail: bengsig@oracle.com, bengsig@oracle.nl
ORACLE Corporation    Path:   uunet!orcenl!bengsig

            "Stepping in others footsteps, doesn't bring you ahead"

karl@ima.isc.com (Karl Heuer) (01/15/91)

[DEC's compiler apparently allows you to write things like
	struct {
	    variant_union { int x; float y; } superfluous;
	} str;
and write str.x to reference the components.  Doug Gwyn notes that this is
gross, nonstandard, etc.]

In article <1991Jan13.072418.1745@nntp-server.caltech.edu> gceych@juliet.caltech.edu writes:
>The piece of code of which this is a small part contains so many system
>calls, kludges, etc. that portability is not a major concern.

I'll accept your judgement on that point.

>Besides, I happen to LIKE this particular construct for nested structures and
>unions (as an option).

I like the functionality, but not the syntax.  The "anonymous union"
	struct {
	    union { int x; float y; };
	} str;
is much better.  This, too, is not part of the current ANSI C Standard, but it
stands a much better chance of being accepted into C-2001.

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