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

next in thread | previous in thread | raw e-mail | index | archive | help
> 
> 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."

 [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 -



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?199808050144.VAA17156>