Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > UNION global variabl initialize

Reply
Thread Tools

UNION global variabl initialize

 
 
James Kuyper
Guest
Posts: n/a
 
      09-14-2011
On 09/14/2011 12:50 PM, Kenneth Brody wrote:
> On 9/13/2011 5:45 PM, James Kuyper wrote:
>> On 09/13/2011 04:29 PM, Kenneth Brody wrote:

> [...]
>>> Question:
>>>
>>> If one defines two different unions, consisting of the same members, but in
>>> a different order, are they guaranteed to be equivalent?
>>>
>>> union foo {
>>> int i;
>>> float f;
>>> char *pt;
>>> };
>>>
>>> union bar {
>>> char *pt;
>>> int i;
>>> float f;
>>> };
>>>
>>> Given 6.7.2.1p14, I would think so:
>>>
>>>> A pointer to a union object, suitably converted, points to each of its
>>>> members (or if a member is a bitfield, then to the unit in which it
>>>> resides), and vice versa.

>>
>> That's quite plausible, but the standard makes no guarantees about it.
>> In particular, it does not say that union foo is compatible with union
>> bar. Among other implications is that a conforming implementation of C
>> is not required to consider the possibility that an a union foo* and a
>> union bar* might alias each other. Consider the following code:
>>
>> void func(union foo *pf, union bar *pb)
>> {
>> for(; pf->i; pf++)
>> pf->i = pb->i;
>> }
> >
> > A conforming implementation of C could optimize that code into the
> > equivalent of

> [...]
>
> Okay, but I think of that as one of those generic "you lied to the compiler
> when you told it that these two pointers never point to the same object"
> type of situations.


But I didn't; that would be equivalent to using the 'restrict' keyword,
which would enable the same optimization, regardless of the type of pb.
All that I promised is that the pointers never point to objects of the
same type. It is section 6.5p7 which, as a result of the fact that these
pointers do not point at compatible types, implies that they therefore
cannot point at the same object.

>>> Of course, doing so, just to make the "correct" member be initialized to
>>> zero, would be "unusual" to say the least.

>>
>> 6.2.7p1:
>> "Moreover, two structure, union, or enumerated types declared in
>> separate translation units are compatible if their tags and members
>> satisfy the following requirements: If one is declared with a tag, the
>> other shall be declared with the same tag. If both are complete types,
>> then the following additional requirements apply: there shall be a
>> one-to-one correspondence between their members such that each pair of
>> corresponding members are declared with compatible types, and such that
>> if one member of a corresponding pair is declared with a name, the
>> other member is declared with the same name. For two structures,
>> corresponding members shall be declared in the same order. For two
>> structures or unions, corresponding bit-fields shall have the same widths."
>>
>> Note that if "union foo" and "union bar" had been given the same tag in
>> different translation units, they would have be compatible. The
>> requirement that the members be declared in the same order applies only
>> to structures, not to unions or enumerations.

>
> I find it hard to believe that the Standard would allow the following:
>
> ===== fileA.C
>
> union foo {
> int i;
> float f;
> char *pt;
> };
>
> ...
>
> ===== fileB.C
>
> union foo {
> float f;
> char *pt;
> int i;
> };
>
> union bar {
> float f;
> char *pt;
> int i;
> };
>
> =====
>
> And have unions "foo" and "bar" in fileB.C not be equivalent.


I agree that they are "equivalent" in many ways. However, they're not
required to be compatible, and as a result there's a number of
associated guarantees in the standard that do NOT apply - the most
important that I can think of being the aliasing issue I've already
raised. As a result, you cannot safely use one in place of the other,
which means that they are not equivalent for all purposes.

> ... And, if
> fileB's bar is equivalent to its foo, and its foo is equivalent to fileA's
> foo, then fileB's foo must also be equivalent to fileA's foo.
>
> And, if fileB's foo is removed, its bar still remains equivalent.
>
> That's not to say you can convert a "foo*" to a "bar*" without an explicit
> cast. It's just that the cast is perfectly legal, and invokes no
> non-standard behavior.


There's nothing in the standard that guarantees that the unions have the
same alignment requirements - though there's obviously no reason for
them being different. In principle, therefore, even the cast is not
guaranteed to be safe.

However, the more serious problem is that dereferencing the resulting
pointer value violates 6.5p7 because the standard doesn't say that foo
and bar are compatible types.

....
> Again, I can't see actually doing such a thing just to default-initialize a
> different "first" member.


Agreed. Explicitly initializing the desired member seems the more
appropriate solution, even in C90, where you have to do so outside the
initializer.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Initialize global variable before any other global variables jubelbrus C++ 5 07-20-2007 06:38 PM
if instance variable get initialize after assigning some values or after constructor then when does static variable get initialize Tony Morris Java 3 02-04-2006 08:39 AM
How to initialize a member of union type alexwu C++ 2 09-12-2004 11:27 PM
union in struct without union name Peter Dunker C Programming 2 04-26-2004 07:23 PM
map XML union to C union (and vice-versa) Matt Garman XML 1 04-25-2004 12:40 AM



Advertisments