[comp.lang.c] Union element alignment query

curry@hplred.HP.COM (Bo Curry) (11/16/90)

A simple question for the wizards:

Assume I define

union {
   FOOTYPE	a[4];
   BARTYPE        b;
} combo;

Does the standard guarantee that (void *)(&combo.a[0]) == (void *)(&combo.b) ?

Thanks,

Bo Curry
curry@hplabs.hpl.hp.com

gwyn@smoke.brl.mil (Doug Gwyn) (11/17/90)

In article <810001@hplred.HP.COM> curry@hplred.HP.COM (Bo Curry) writes:
>Does the standard guarantee that (void *)(&combo.a[0]) == (void *)(&combo.b) ?

Yes, as a consequence of a requirement in 3.5.2.1 Semantics combined with
the property of void* as a universal object pointer type.

henry@zoo.toronto.edu (Henry Spencer) (11/18/90)

In article <810001@hplred.HP.COM> curry@hplred.HP.COM (Bo Curry) writes:
>union {
>   FOOTYPE	a[4];
>   BARTYPE        b;
>} combo;
>
>Does the standard guarantee that (void *)(&combo.a[0]) == (void *)(&combo.b) ?

It guarantees (3.5.2.1) that a pointer to the union points to each of its
members, after suitable conversion.  That is not *quite* what you are
asking, but I think it would take a seriously bizarre implementation to
do otherwise.  It may be possible to prove your equality, although it
would take non-trivial reasoning.
-- 
"I don't *want* to be normal!"         | Henry Spencer at U of Toronto Zoology
"Not to worry."                        |  henry@zoo.toronto.edu   utzoo!henry

steve@taumet.com (Stephen Clamage) (11/18/90)

curry@hplred.HP.COM (Bo Curry) writes:

!union {
!   FOOTYPE	a[4];
!   BARTYPE        b;
!} combo;

!Does the standard guarantee that (void *)(&combo.a[0]) == (void *)(&combo.b) ?

Not exactly.  The standard (section 3.5.2.1) requires that
	(FOOTYPE*)&combo == &combo.a[0]
and that
	(BARTYPE*)&combo == &combo.b
There is also a requirement that given a type T, and the declaration
	T* t;
then
	(T*)(void*)t == t;
I don't believe that there is any requirement that the relation you specify
must hold.  On machines where pointers to different types may have
different sizes, their conversions to void* might not be equal.  The
standard only requires that conversion from void* back to the original
pointer type must work.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

steve@taumet.com (Stephen Clamage) (11/18/90)

steve@taumet.com (Stephen Clamage) writes:

>There is also a requirement that given a type T, and the declaration
>	T* t;
>then
>	(T*)(void*)t == t;

I didn't state this very well.  I meant to say:

There is also a requirement that given an object type T, and the declaration
	T* t;
then the relation
	(T*)(void*)t == t
must hold.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

msb@sq.sq.com (Mark Brader) (11/22/90)

> > union {
> > FOOTYPE	a[4];
> > BARTYPE        b;
> > } combo;
> > Does the standard guarantee 
> > (void *)(&combo.a[0]) == (void *)(&combo.b) ?
> 
> Not exactly.  The standard (section 3.5.2.1) requires that
> 	(FOOTYPE*)&combo == &combo.a[0]

No, combo.a is the union member, not combo.a[0].  So this should be:

	(FOOTYPE(*)[4])&combo == &combo.a

The actual wording in 3.5.2.1 is:

#  A pointer to a union object, suitably converted, points to each
#  of its members (or if the member is a bit-field, then to the unit
#  in which it resides), and vice versa.

One sticking point is the meaning of "suitably converted".  When I
casually read this before, I assumed that converting either pointer
to void * would be "suitable".  (The other pointer in the comparison
would then be implicitly converted to void * also.)  In that case,
 
	&combo == (void *)&combo.a
and	&combo == (void *)&combo.b

and therefore

	(void *)&combo.a == (void *)&combo.b

But the stricter interpretation, guaranteeing only

	(FOOTYPE(*)[4])&combo == &combo.a
and	(BARTYPE *)&combo == &combo.b
and	&combo = (union ... *)&combo.a
and	&combo = (union ... *)&combo.b

also seems to be legitimate.  We'd have to have an interpretation ruling
to settle this, I think.  Anyway, note the last two equalities.  They
imply that

	(void *)(union ... *)&combo.a == (void *)(union ... *)&combo.b

but, as there isn't any direct guarantee that

	(void *)(TYPE *)foop == (void *)foop

, this probably doesn't help.

Likewise, there is no guarantee that a pointer to an array, suitably
converted, points to its first element, or vice versa.  That is, even if

	(void *)&combo.a == (void *)&combo.b

is true, the equality originally asked about does not seem to follow.

It is, of course, possible that some of these things are indirectly
guaranteed, and I haven't noticed.

-- 
Mark Brader		"'Settlor', (i) in relation to a testamentary trust,
Toronto			 means the individual referred to in paragraph (i)."
utzoo!sq!msb, msb@sq.com		-- Income Tax Act of Canada, 108(1)(h)

This article is in the public domain.