[net.lang.c] Standard for union initialization?

Joseph I. Pallas <PALLAS@SU-SCORE.ARPA> (01/04/85)

Perhaps I'm out of touch.... An article I read about the draft
standard said the standard would allow initialization of unions, but
the first union field would be the type used for the initialization.

Instead of insisting on

	union {
	    <type1> foo;
	    <type2> bar;
	    <type3> mumble;
	} baz = <type1 initializer>;

why not use a more general scheme like

	union {
	    <type1> foo;
	    <type2> bar;
	    <type3> mumble;
	} baz.mumble = <type3 initializer>;

Since no existing compiler that I know of lets you initialize unions
at all currently, there's nothing to be lost by going with the more
flexible system.

joe
-------

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (01/05/85)

> why not use a more general scheme like
> 
> 	union {
> 	    <type1> foo;
> 	    <type2> bar;
> 	    <type3> mumble;
> 	} baz.mumble = <type3 initializer>;

But "baz.mumble" is not what you want the union to be called.
This addition would certainly make for a messier language
syntax definition.

ndiamond@watdaisy.UUCP (Norman Diamond) (01/07/85)

> > why not use a more general scheme like
> > 
> > 	union {
> > 	    <type1> foo;
> > 	    <type2> bar;
> > 	    <type3> mumble;
> > 	} baz.mumble = <type3 initializer>;
> 
> But "baz.mumble" is not what you want the union to be called.
> This addition would certainly make for a messier language
> syntax definition.

Why not fix the syntax of that scheme and use its semantics:

union {
    <type1> foo;
    <type2> bar;
    <type3> mumble;
} baz = (type3) <initializer>;

Suppose the same type is duplicated in the union, e.g. suppose type3 is
the same as type1 and the compiler doesn't know whether to initialize
foo or mumble?  Let the compiler choose whichever valid one it wishes;
the result would be equivalent.

This would not make the language any messier; it is better than many
other examples of casts.  And it would be useful, and it would not break
existing programs.

-- Norman Diamond

UUCP:  {decvax|utzoo|ihnp4|allegra|clyde}!watmath!watdaisy!ndiamond
CSNET: ndiamond%watdaisy@waterloo.csnet
ARPA:  ndiamond%watdaisy%waterloo.csnet@csnet-relay.arpa

"Opinions are those of the keyboard, and do not reflect on me or higher-ups."

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (01/08/85)

> union {
>     <type1> foo;
>     <type2> bar;
>     <type3> mumble;
> } baz = (type3) <initializer>;

This is the closest thing to a solution yet.
Still hard to fit into a regular grammar,
since "(type)constant" is already understood
as a valid constant in this context.
However, if the "initialize first member"
rule is adopted, the above example would still
work in some (not all) cases.

kpmartin@watmath.UUCP (Kevin Martin) (01/14/85)

>Why not fix the syntax of that scheme and use its semantics:
>
>union {
>    <type1> foo;
>    <type2> bar;
>    <type3> mumble;
>} baz = (type3) <initializer>;
>
>Suppose the same type is duplicated in the union, e.g. suppose type3 is
>the same as type1 and the compiler doesn't know whether to initialize
>foo or mumble?  Let the compiler choose whichever valid one it wishes;
>the result would be equivalent.
>This would not make the language any messier; it is better than many
>other examples of casts.  And it would be useful, and it would not break
>existing programs.
>-- Norman Diamond
This only works if you either extend the syntax to allow "casting" of
aggregate initializers, or if you *still* don't allow initialization
of a union of structures.

Either way, this is less clear than an initializer of the form
	element = value
e.g.
union {
	<type1> foo;
	<type2> bar;
	<type3> mumble;
}baz = mumble = <initializer>;
Since <initializer> can be an expression in C already, you might find that
your compiler's grammar already allows this, and it is only detected as
an error after further analysis.

Of course, if the "element =" is absent, the first element could be
initialized. Similarly for the implicit zeroing of un-initialized
static storage.
            Kevin Martin, UofW Software Development Group.

jim@ISM780B.UUCP (01/14/85)

>> union {
>>     <type1> foo;
>>     <type2> bar;
>>     <type3> mumble;
>> } baz = (type3) <initializer>;
>
>This is the closest thing to a solution yet.
>Still hard to fit into a regular grammar,
>since "(type)constant" is already understood
>as a valid constant in this context.

I don't really see this as much of a problem.  Given

union {
	long  l;
	short s;
} u = (short)47;

With the first member method the constant (short)47 is converted to
long before being stored.  With the proposed method, it isn't converted
before being stored.  Period.  Of course, there still is the need to check
whether the type of the initializer is the same as that of any of the members,
and either complain (safe) or convert to the type of the first member
(convenient) if not.

>However, if the "initialize first member"
>rule is adopted, the above example would still
>work in some (not all) cases.

Not on your life.  In the example given above, it will work on machines
where the short shares the low order part of the word (e.g., VAX)
but not where it shares the high order part (e.g., 370, pdp11).
From the point of view of portability, things that work on some machines but
not others are much worse than things that don't work at all.
Witness all the effort that has gone into fixing byte order problems,
and pdp11 code which assumes that an int is 2 bytes, and code that assumes
that int == long (which 32-bit machine users are producing in great
quantities, with plenty of encouragement from the 4.2BSD manual).
Is that what you really want?

The ANSI committee has a responsibility to do it right if they are going
to do it at all.  This notion that "well, we gotta have something
and the first member method is easy" is indefensible.  If they can't
figure out or are not willing to use a method that solves the problem
completely, then they have no business changing the language at all.
The syntax argument above is the strongest I have seen against the (cast)
method, and it doesn't seem overwhelming to me.

-- Jim Balter, INTERACTIVE Systems (ima!jim)

ndiamond@watdaisy.UUCP (Norman Diamond) (01/14/85)

Kevin Martin proposes an initializer of the form:
> 	element = value
> e.g.
> union {
> 	<type1> foo;
> 	<type2> bar;
> 	<type3> mumble;
> }baz = mumble = <initializer>;
> Since <initializer> can be an expression in C already, you might find that
> your compiler's grammar already allows this, and it is only detected as
> an error after further analysis.
> 
> Of course, if the "element =" is absent, the first element could be
> initialized. Similarly for the implicit zeroing of un-initialized
> static storage.

What is the datatype of "mumble"?  Assigning mumble = <initializer> or
mumble = <anything> should cause an error, unless <anything> is an int
or near-relative of an int.  And then, how can mumble be used as the
initializer for baz?

-- Norman Diamond

UUCP:  {decvax|utzoo|ihnp4|allegra|clyde}!watmath!watdaisy!ndiamond
CSNET: ndiamond%watdaisy@waterloo.csnet
ARPA:  ndiamond%watdaisy%waterloo.csnet@csnet-relay.arpa

"Opinions are those of the keyboard, and do not reflect on me or higher-ups."

hokey@plus5.UUCP (Hokey) (01/15/85)

For starters, I hope people have been reading the discusison pertaining to
union initialization in mod.std.c.

After reading the note in mod.std.c from the Chair of the C Standards
Committee, however, I don't know if the discussion is good for anything;
he said the Committee decided on the "first element" rule and the issue
is closed.  I would *love* to see enough feedback on the issue to cause
the Committee to change their position.

Now, if only the Unix standards group would consider changing lockf()...
-- 
Hokey           ..ihnp4!plus5!hokey
		  314-725-9492

henry@utzoo.UUCP (Henry Spencer) (01/15/85)

> Either way, this is less clear than an initializer of the form
> 	element = value
> e.g.
> union {
> 	<type1> foo;
> 	<type2> bar;
> 	<type3> mumble;
> }baz = mumble = <initializer>;

How do you use this to initialize a union inside a structure?
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,linus,decvax}!utzoo!henry

uddeborg@chalmers.UUCP (G|ran Uddeborg) (01/17/85)

In article <10884@watmath.UUCP> kpmartin@watmath.UUCP (Kevin Martin) writes:
	...
>union {
>	<type1> foo;
>	<type2> bar;
>	<type3> mumble;
>}baz = mumble = <initializer>;
>Since <initializer> can be an expression in C already, you might find that
>your compiler's grammar already allows this, and it is only detected as
>an error after further analysis.
>
>Of course, if the "element =" is absent, the first element could be
>initialized. Similarly for the implicit zeroing of un-initialized
>static storage.
>            Kevin Martin, UofW Software Development Group.


What about the ".=" operator discussed elsewhere in this group? :-)
-- 
"For me, UNIX is a way of being."  (Originally: Armando P. Stettner)

		G|ran Uddeborg
		{seismo,philabs,decvax}!mcvax!enea!chalmers!uddeborg

rpw3@redwood.UUCP (Rob Warnock) (01/17/85)

Notice that the "first element" rule makes it virtually impossible to
do things like initialize symbol tables at compile time, unless you
give up using unions. The whole point of unions is that they can vary,
but if I can only initialize one to the first "type", how do I initialize
an array of them, some of which are of various types?


Rob Warnock
Systems Architecture Consultant

UUCP:	{ihnp4,ucbvax!dual}!fortune!redwood!rpw3
DDD:	(415)572-2607
USPS:	510 Trinidad Lane, Foster City, CA  94404

kpmartin@watmath.UUCP (Kevin Martin) (01/18/85)

In article <4930@utzoo.UUCP> henry@utzoo.UUCP (Henry Spencer) asks:
>> Either way, this is less clear than an initializer of the form
>> 	element = value
>> e.g.
>> union {
>> 	<type1> foo;
>> 	<type2> bar;
>> 	<type3> mumble;
>> }baz = mumble = <initializer>;
>
>How do you use this to initialize a union inside a structure?


    struct foo {
        int bar;
        char *blech;
        union {
            float float_val;
            char char_val;
            long long_val;
        } onion;
    };

    struct foo x = {
        42,                     /* value for x.bar */
        "value for x.blech",
        char_val = 'x'          /* value for x.onion.char_val */
    };                          /* value for x */

-or- (adding full {}'s)
    struct foo x = {
        42,                     /* value for x.bar */
        "value for x.blech",
        {
            char_val = 'x'      /* value for x.onion.char_val */
        }                       /* value for x.onion */
    };                          /* value for x */


And, seeing as I see the next question coming...
>How do yo initialize a structure inside a union?
Well, this is where your YACC grammer may actually need changes (but this
applies to the name-the-type suggestion too...)

    union foo {
        int bar;
        char *blech;
        struct {
            float fred;
            char herbie;
            long harry;
        } stroct;
    };

    union foo x = {
        stroct = {
            4.2,                /* value for x.stroct.fred */
            'x',                /* value for x.stroct.herbie */
            0x12345678          /* value for x.stroct.harry */
        }                       /* value for x.stroct */
    };                          /* value for x */

-or- (removing extra {} )
    union foo x =
        stroct =
            4.2,                /* value for x.stroct.fred */
            'x',                /* value for x.stroct.herbie */
            0x12345678          /* value for x.stroct.harry */
    ;                           /* value for x */
(You would need the inner {} in this example, say, if you wanted
x.stroct.harry to be *implicitly* initialized to zero)

                        Kevin Martin, UofW Software Development Group

dick@tjalk.UUCP (Dick Grune) (01/21/85)

I saw a suggestion in net.lang.c a few months ago that I found very sensible,
readable and hygienic:

	union	{
		int i;
		float x;
		char *str;
	} ixstr = { , 3.14, };

if you want it to start off as a float, etc.

Note that:
1. it is (almost) isomorphous to a struct initialization,
2. it also works nicely for arrays of unions.

					Dick Grune
					Vrije Universiteit
					de Boelelaan 1081
					1081 HV  Amsterdam
					the Netherlands

... and my name isn't Richard.

MLY.G.SHADES%MIT-OZ@MIT-MC.ARPA (01/23/85)

in response to Dick Grune's <dick at tjalk.uucp> message on union init
it seems rather messy to me as the number of commas must be precise.
for example:

	union
	{
		char	ec;
		int	i;
		float	sreal;
		char	*str;
	} ini_union = { ,3.14 }

	here you would want to init the float but the int would be
inited instead with 3 under some compiler without warning.

                          shades@mit-oz.arpa

p.s. and what about commented in/out variables?

guido@boring.UUCP (01/24/85)

In article <7647@brl-tgr.ARPA> MLY.G.SHADES%MIT-OZ@MIT-MC.ARPA writes:
>p.s. and what about commented in/out variables?

Uh, your p.s. applies equally well to struct initializations.  Are you
proposing another standard for that, too?  You're kidding!

I wholeheartedly second Dick's proposal.  Long live C!

	Guido van Rossum, "Stamp Out BASIC" Committee, CWI, Amsterdam
	guido@mcvax.UUCP

jim@ISM780B.UUCP (02/02/85)

>"Intelligent idea"??? This is just another accident waiting to happen!
>This looks ok for a nice short example like this, but frequently, the
>union's definition and initialization are far apart (and maybe in different
>source files). This makes it easy to add another union element, and
>inadvertantly screw up the initializers royally without as much as a
>peep from the compiler.

I don't disagree with your observation, but please note that the
same argument can be applied to structure initialization.  The reason that it
is a nice idea is that it is isomorphic to structure initialization, so it
fits the existing structure; it doesn't involve any new mechanism, so it fits
within the committee's conservative charter.

Arguing that C's method of structure initialization is dangerous is a totally
different discussion; come up with better ideas for structure initialization,
and you will have come up with better ideas for union initialization.

-- Jim Balter, INTERACTIVE Systems (ima!jim)