From: Joshua Maurice on
On Nov 9, 12:01 pm, Francis Glassborow
<francis.glassbo...(a)btinternet.com> wrote:
> Trying to read a union through a different field than the one by
> which it was written is strictly undefined behaviour (there are some
> special cases which are exceptions).

I believe this is the intended reading of the C and C++ standards.
However, do note that (nearly) all C and C++ compilers, as an
extension, allow type punning through unions.

This also is related to the standard's "guarantee" that you're allowed
to read and write to any POD through a char* or unsigned char*, except
that this guarantee is never explicitly spelled out, but merely hinted
at in several places.

IIRC, your last option for type punning is memcpy, and I don't recall
if the standard's guarantees are stronger than the char* and unsigned
char* guarantees.

The whole thing is a black art due to the vagueness of the standard,
misinformation, and extensions supported by every compiler (the union
type punning) which many people rely on,but which isn't in the
standard.

PS: Do note that unions are evil because of their associated bug in
the C and C++ standard:

//translation unit 1
void foo(int& x, float& y);
int main()
{
int x = 1;
float y = 2;
foo(x, y);
return x;
}

//translation unit 2
void foo(int& x, float& y) { x = y; }

The strict aliasing rule was intended to allow the compiler to
optimize assuming sufficiently different typed pointers due not alias.
However, a union can make them alias. Thus, a compiler which compiles
separate translation units separately (which is intended by the
standard), and which makes optimization assumptions using strict
aliasing (which is intended by the standard), when compiling a program
using a union, will result in a program broken. In translation unit 1,
the compiler sees the union, and can know that the types int and float
may alias. However, in translation unit 2, the compiler will optimize
assuming that x and y do not alias, and bad things can happen because
they actually do alias. (Or at least for a slightly more complex
function foo bad things may happen.) Moral of this story: don't use
unions, and when you must, don't let references to union members
escape the translation unit (or however it actually works out in
practice, as I am ill informed).


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: krishna on
On Nov 9, 12:01 pm, Francis Glassborow
<francis.glassbo...(a)btinternet.com> wrote:
> krishna wrote:
> > int main()
> > {
> > union my_union{
> > int i;
> > float f;
> > };
> > my_union u;
> > u.f = 2.0;
> > std::cout << u.i;
> > }
>
> > why is int casted value of u.f not given? (the start address is the
> > same for all the members).
>
> > -Krishna.
>
> FOFL
> That is not how unions work. They are a way of recycling memory and at
> any one time the bit pattern stored in one represents exactly one of the
> fields. Trying to read a union through a different field than the one by
> which it was written is strictly undefined behaviour (there are some
> special cases which are exceptions) What you did was to initialise u as
> a float and then try to read it as an int. Officially the program can do
> anything, in practice (in this case) it will probably just reinterpret
> the stored bit pattern (as many bits as it needs) as an int. If the
> result happens to be a trap value then your program may stop.

{ edits: quoted banner removed. please don't quote the banner. -mod }

Not until I read ur reply, I realized it's the bit pattern
reinterpretation (and that's wat I had in my mind) and float bit
pattern is quite distinct than int, that explains it, I shouldn't have
used the term casting as in "why casted value not given".

Thanks,
Krishna


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: red floyd on
On Nov 9, 1:59 pm, Neil Butterworth <nbutterworth1...(a)gmail.com>
wrote:
> Francis Glassborow wrote:
>
> > FOFL
> > That is not how unions work. They are a way of recycling memory and at
> > any one time the bit pattern stored in one represents exactly one of the
> > fields. Trying to read a union through a different field than the one by
> > which it was written is strictly undefined behaviour
>
> By which you presumably are referring to 9.5/1:
>
> "In a union, at most one of the data members can be active at any time,
> that is, the value of at most one of the data members can be stored in a
> union at any time."
>
> and by:
>
> > (there are some
> > special cases which are exceptions)
>
> to:
>
> "[Note: one special guarantee is made in order to
> simplify the use of unions: If a POD-union contains several POD-structs
> that share a common initial sequence (9.2), and if an object of this
> POD-union type contains one of the POD-structs, it is permitted to
> inspect the common initial sequence of any of POD-struct members; see
> 9.2." ]
>
> My question is what does the "special guarantee" described in the second
> quote from the Standard actually mean? Can you (or someone else) post a
> simple example illustrating it?
>

I believe it's something like this:

struct X {
int tag;
double d;
};

struct Y {
int tag;
char text[10];
};

union {
X x;
Y y;
};

void f()
{

u.x.tag = 3;

int n = u.y.tag;
}

I believe that in this case, the value of n is well defined.



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Nick Hounsome on
On 10 Nov, 08:24, stan <smo...(a)exis.net> wrote:
> Francis Glassborow wrote:
>
> <union question snipped>
>
> > That is not how unions work. They are a way of recycling memory and at
> > any one time the bit pattern stored in one represents exactly one of the
> > fields. Trying to read a union through a different field than the one by
> > which it was written is strictly undefined behaviour (there are some
> > special cases which are exceptions) What you did was to initialise u as
> > a float and then try to read it as an int. Officially the program can do
> > anything, in practice (in this case) it will probably just reinterpret
> > the stored bit pattern (as many bits as it needs) as an int. If the
> > result happens to be a trap value then your program may stop.
>
> I don't have a copy handy, so I ask. Is this really undefined behavior
> or implementation defined? I'm not questioning the cautionary advice;
> I get it.

I would guess that, in principle, it must be undefined because you
could imagine a processor for which not all bit patterns represent a
valid number of some type and the processor could through a wobbly.

One thing to consider might be a signalling NaN

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]