brnstnd@stealth.acf.nyu.edu (02/17/90)
Try this program on your favorite compiler:
#include <stdio.h>
struct str { char c[20]; } ;
static struct str test;
static union { struct { void *v; struct str s; } c; struct str s; } u;
static char c = '\0'; /* don't-crash kludge */
main()
{
int i; for (i = 0;i < 15;i++) test.c[i] = 'a' + i;
u.s = test; puts(u.s.c);
u.c.s = u.s; puts(u.c.s.c);
u.s = u.c.s; puts(u.s.c);
}
It looks valid to me: after u.s = test, u.s is active, so accessing u.s
is fine; then after u.c.s = u.s, u.c.s is active, so accessing u.c.s is
fine; and so on. Is there an ANSI rule prohibiting this? If not, quite a
few supposedly conformant compilers are broken.
---Dan
henry@utzoo.uucp (Henry Spencer) (02/18/90)
In article <21694:03:07:21@stealth.acf.nyu.edu> brnstnd@stealth.acf.nyu.edu (Dan Bernstein) writes: > u.c.s = u.s; puts(u.c.s.c); >... Is there an ANSI rule prohibiting this? If not, quite a >few supposedly conformant compilers are broken. The Holy Scriptures (Oct 88 draft), epistle 3.3.16.1, sayeth: "If the value being stored in an object is accessed from another object that overlaps in any way the storage of the first object, then the overlap shall be exact and the two objects shall have... a compatible type; otherwise the behavior is undefined." The underlying reasoning here is that (a) assignment must, in general, go via a temporary if overlapping operands are to work properly, (b) it is very difficult for the compiler to tell when a temporary is required, and (c) use of a temporary can impose a serious efficiency penalty. So C has historically required you to provide the temporary yourself if it is necessary, and ANSI C continues that rule. -- "The N in NFS stands for Not, | Henry Spencer at U of Toronto Zoology or Need, or perhaps Nightmare"| uunet!attcan!utzoo!henry henry@zoo.toronto.edu