[comp.lang.c] Does ANSI prohibit assignments between overlapping union components?

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