Prev: union members accessed with another member (whose data type requires less space)
Next: Function template specialization
From: Joshua Maurice on 9 Nov 2009 15:24 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 9 Nov 2009 15:28 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 9 Nov 2009 15:27 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 9 Nov 2009 19:59
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! ] |