Click here to Skip to main content
15,891,529 members
Please Sign up or sign in to vote.
1.80/5 (2 votes)
See more:
hi in the following code:
C++
// t4.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

struct S
{
	union
	{
		struct
		{
			float f1;
			bool b;
		};
		struct
		{
			bool b;
			char c;
			float f2;
		};
	};
};

int _tmain(int argc, _TCHAR* argv[])
{
	S s;
	s.b = true;
	s.f2 = 1.00;
	return 0;
}

when s.f2 is initialized, s.b becomes false!
is it a bug?! i tried VS2008 and VS2010 and this happens in both.
what's the problem?
thx
Posted

Perhaps you need to look up what unions are actually used for:
http://www.cplusplus.com/doc/tutorial/other_data_types/[^]

They're used for sharing the same memory with different data types. Since you're sharing the same memory space, changing the second structure is of course affecting the first.
 
Share this answer
 
1. You've used the tag C++ for this question, yet you are using outdated C-Syntax. union is an unsafe construct from the C language that is only still available in C++ for compatibility reasons. C++ provides safe alternate means to implement anything that you would otherwise use a union for, such as class hierarchies, and inheritance.

2. There is a reason for rule 1. above: unions are unsafe. After your own experience you should recognize why. You and you alone are responsible for correctly accessing your union - neither the compiler nor the runtime can do that for you! If at one point you enter values into s1, then any accesses to s2 become invalid!
It is your responsibility to ensure that you always acces the correct struct - the one that was last initialized.

3. As Richard already pointed out, it isn't exactly helpful to use unnamed structs. This is yet another remnant of C Syntax that should best be forgotten! See Solution 2.

4. While I've pointed out in 1. that you shouldn't be using union in the first place, if you choose to ignore that advice, at the very least add one attribute to your struct S that indicates the struct that is currently being used. E. g. something like this:
C++
struct S {
   int utype;
   union {
      struct {
          bool b;
          float f1;
      } s1;
      struct {
          float f2;
          int i;
          bool b;
      } s2;
   }
}
int main() {
   S my_s;
   // now insert some values:
   my_s.utype = 1; // using s1 now
   my_s.s1.b = true;
   my_s.s1.f1 = 3.14;
   // now do something completely different 
   // ...
   // now read from your struct, but check it's current usage first:
   bool my_b;
   float my_f;
   if (my_s.utype == 1) {
      // Ok. Using s1:
      my_b = my_s.s1.b;
      my_f = my_s.s1.f1;
   }
   else {
      // someone changed the usage to s2 in the meantime! So use s2 now:
      my_b = my_s.s2.b;
      my_f = my_s.s2.f2;
   }
}

While this is much safer than your previous code, it's still awkward that you always have to specifically point out or inquire what part of the union you are using. Using classes and inheritance with a few get and set functions would be a lot easier.
 
Share this answer
 
You have a bool b in both structures of the union so any reference to S.b will refer to the one in the first structure. Changes then made to the second structure may (will) corrupt it. Choose different names in each structure, or give each structure a name to avoid ambiguity; something like:
C++
struct S
{
    union
    {
        struct
        {
            float f1;
            bool b;
        } s1;
        struct
        {
            bool b;
            char c;
            float f2;
        } s2;
    };
};
 
int _tmain(int argc, _TCHAR* argv[])
{
	S s;
	s.s2.b = true;
	s.s2.f2 = 1.00;
	return 0;
}
 
Share this answer
 
I'm not a C++ guy, but based on the skim I just did of the union type, perhaps the .b that gets set in the first statement is the b in the first struct in the union, but when you set .f2, it changes the "type" of the union to the second struct, where the b variable hasn't been set? Just a guess.
 
Share this answer
 
solution 4:
rehi
thank u for participating. :)

- You've used the tag C++ for this question, yet you are using outdated C-Syntax.
is there any part of this site to be dedicated to pure C-Syntax issues?

- union is unsafe.
what do u mean by unsafe?! u mean it has no predictable behavior?! i think it's a reliable data structure that works as it's expected to. if neither the compiler nor the runtime get involved in looking after whether i've treated properly with the union, does it mean that it's unsafe?! i myself is responsible for keeping its safety, right. but this doesn't mean that it's an unsafe data structure!

- If at one point you enter values into s1, then any accesses to s2 become invalid!
what do u mean? assigning values into s1 affects on values currently in s2, but this doesn't mean that accessing variables in s2 becomes invalid! at the same time accessing both s1 and s2 is a valid thing. it's a union, not a switch! ur view to a union as the utype attribute indicates is like a switch, while unions are different from switches. in many cases we deliberately mean this affect. like:
C++
union
{
	struct
	{
		BYTE day;
		BYTE month;
		WORD year;
	};
	DWORD date;
};

- it isn't exactly helpful to use unnamed structs. This is yet another remnant of C Syntax that should best be forgotten!
in such an example we see its helpfulness. using unions with unname structs is easier and eliminates need for specifying the struct in which the member is defined. how do u say that it's not helpful?! why is it best to be forgotten?! i certainly can't agree with u! i think ur a high-level programmer and prefer to use new technologies, while i prefer to be a low-level programmer and relegate less things to the compiler.
---------------------
Solution 5:

ur right, changing a member of the first struct affects on values of members of the second struct and vice versa. but my question was to know the way the compiler interprets this. when i change b and don't mention which b i mean i expect that the compiler encounter no ambiguity in assigning the value into the proper member. i expect it to make only one b in the union and treats the union as:
C++
struct
{
	bool b;
	union
	{
		struct
		{
			float f1;
		};
		struct
		{
			char c;
			float f2;
		};
	};
};

otherwise, it must generate an ambiguity error so that i explicitly specify which b i mean.
thx
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900