Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 4 Aug 1998 21:12:40 -0400 (EDT)
From:      Chuck Robey <chuckr@glue.umd.edu>
To:        Thomas David Rivers <rivers@dignus.com>
Cc:        freebsd-hackers@FreeBSD.ORG, Nicolas.Souchu@prism.uvsq.fr
Subject:   Re: C and static initialization with unions
Message-ID:  <Pine.BSF.4.00.9808042107000.409-100000@picnic.mat.net>
In-Reply-To: <199808050144.VAA17156@lakes.dignus.com>

next in thread | previous in thread | raw e-mail | index | archive | help

On Tue, 4 Aug 1998, Thomas David Rivers wrote:

> > 
> > On Tue, 4 Aug 1998, Thomas David Rivers wrote:
> > 
> > >  Also - you should be aware that ANSI forbids assigning to one element
> > >  of a union and referencing a different element.   (Basically, the
> > >  'type-punning' problem) C compilers are allowed to optimize field 
> > >  references based on type; so that:
> > > 
> > >  main() 
> > >  {
> > >   union foo_t foo;
> > >   void *vp;
> > > 
> > >   foo.i = 5;
> > >   foo.p = 0;
> > > 
> > >   if(foo.i) {
> > > 	printf("true\n");
> > >   } else {
> > > 	printf("false\n");
> > >   }
> > >  }
> > > 
> > >  may, depending on the optimizer, print either true or false.   Technically,
> > >  this is an invalid ANSI C program.
> > 
> > I never saw that, and I think you may be wrong, so if you have the ansi
> > standard lying around, give me a quote, ok?  Harbison & Steele says, on
> > page 132-133, that doing what you said above is non-portable (I agree),
> > but programmers "sometimes do this to 'reach under' C's type system 
> > ...".  There was more, but I'm sure you know it already.
> > 
> > 
> 
>  It's in there; believe me (I'm the manager for C/C++ compiler development
>  at SAS Institute...)
> 
>  The ANSI C standard, section 3.3.2.4 says:
> 
>    "With one exception, if a member of a union object is accessed after
>     a value has been stored in a different member of the object, the
>     behaviour is implementation-defined."

And you _seem_ to have made my argument ... you said ANSI forbids it,
you even quoted yourself above, but your quotation from the standard
says it's implementation-defined.  That means it's legal, but undefined
behavior.  For any reasonable shop making software for sale, they may
mean the same thing, but for someone doing one-off controllers, the
operation is clearly legal, and the programmer is clearly warned that
they had better know what they're doing, because it's not going to be
portable.

I'm making a distinction between "forbids" (which I take to mean that 
the compiler must catch it and cause a fatal error) and "non-portable"
(which I take to mean that any reasonable compiler should issue a
warning, and no public shop should use).

That's my argument, if that's wrong, then I'm completely wrong.

> 
>  [The exception is to allow for a "common initial sequence" in which
>   the union contains structures whose first fields are compatible types.
>   We're note dealing with compatible types, or structures, in this 
>   example, so the exception clearly does not apply.]
> 
>  Furthermore, section 3.3 specifies:
> 
>    "An object shall have its stored value accessed only by an lvalue
>     that has one of the following types:
>  
>        o) The declared type of the object
>        o) a qualified version of the declared type of the object
>        o) a type that is the signed or unsigned type corresponding to the
>           declared type of the object
> 	...
> 
>  The point of this particular definition (per the footnote in the
>  standard) is to list exactly when an object may be considered to be
>  aliased.
> 
>  This, the following code is non-ANSI, and may produce surprising
>  results:
> 
> 	char *cp;
> 	int i;
> 
> 	i = 5;
> 	cp = (char *)&i;
> 	*cp = 0x80;  /* 'i' is being incorrectly referenced */
> 	printf("i is 0x%x", i);
> 
>  An ANSI conforming implementation would be correct in generating the
>  output 
> 	i is 5
>  as the compiler, per the rules above, doesn't have to note the aliasing
>  that occured when the stored value of 'i' was incorrectly referenced.
> 
>  In fact, the entire purpose of the list in section 3.3 of the standard
>  is to allow optimizers to do just that (type based aliasing) which 
>  can be a big win for code generation.
> 
> 	- Dave Rivers -
> 
> 
> 
> 

----------------------------+-----------------------------------------------
Chuck Robey                 | Interests include any kind of voice or data 
chuckr@glue.umd.edu         | communications topic, C programming, and Unix.
213 Lakeside Drive Apt T-1  |
Greenbelt, MD 20770         | I run Journey2 and picnic (FreeBSD-current)
(301) 220-2114              | and jaunt (NetBSD).
----------------------------+-----------------------------------------------





To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.00.9808042107000.409-100000>