From owner-freebsd-hackers Tue Aug 4 18:41:11 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id SAA09279 for freebsd-hackers-outgoing; Tue, 4 Aug 1998 18:41:11 -0700 (PDT) (envelope-from owner-freebsd-hackers@FreeBSD.ORG) Received: from elvis.vnet.net (elvis.vnet.net [166.82.1.5]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id SAA09268 for ; Tue, 4 Aug 1998 18:41:08 -0700 (PDT) (envelope-from rivers@dignus.com) Received: from dignus.com (ponds.vnet.net [166.82.177.48]) by elvis.vnet.net (8.8.8/8.8.4) with ESMTP id VAA24233; Tue, 4 Aug 1998 21:40:47 -0400 (EDT) Received: from lakes.dignus.com (lakes [10.0.0.3]) by dignus.com (8.8.8/8.8.5) with ESMTP id WAA03564; Tue, 4 Aug 1998 22:13:42 -0400 (EDT) Received: (from rivers@localhost) by lakes.dignus.com (8.8.8/8.6.9) id VAA17156; Tue, 4 Aug 1998 21:44:52 -0400 (EDT) Date: Tue, 4 Aug 1998 21:44:52 -0400 (EDT) From: Thomas David Rivers Message-Id: <199808050144.VAA17156@lakes.dignus.com> To: chuckr@glue.umd.edu, rivers@dignus.com Subject: Re: C and static initialization with unions Cc: freebsd-hackers@FreeBSD.ORG, Nicolas.Souchu@prism.uvsq.fr In-Reply-To: Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG > > 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