Not logged in, Join Here! or Log In Below:  
 
News Articles Search    
 

 Home / General Programming / Union Initialization Account Manager
 
Archive Notice: This thread is old and no longer active. It is here for reference purposes. This thread was created on an older version of the flipcode forums, before the site closed in 2005. Please keep that in mind as you view this thread, as many of the topics and opinions may be outdated.
 
Dr. Necessiter

May 20, 2005, 07:36 AM

Hey all...

I want to initialize a union with static data, but this always interprets the initializers as the type of the first union member. Unfortunately, I'd like to initialize with data from all the different union types. Something like this:

  1. typedef union
  2.     {
  3.     float   fDef;
  4.     int     iDef;
  5.     char*   cDef;
  6.     UBYTE   uDef;
  7.     } DEFVAL;
  8. DEFVAL  defaults[] = {1.0f, 2, "Hello"};


The first initializer works, the second doesn't cause an error, but it "incorrectly" stuffs the bits for an integer 2 into the float of the union, and the third produces an error.

I can't do a typecast trick like
  1. #define INT2FLOAT(i)  (*(float*)&(i))       // gets a float out of an int

because you can't take the address of a constant like this. Any ideas here? It's frustrating because the data is there in memory properly, I just can't "fool" the compiler into interpreting it the way I'd like.


 
Nils Pipenbrinck

May 20, 2005, 07:54 AM

  1.  
  2. union DEFVAL
  3. {
  4.     float   fDef;
  5.     int     iDef;
  6.     char*   cDef;
  7.     UBYTE   uDef;
  8. public:
  9.     DEFVAL (float a) : fDef(a) {}
  10.     DEFVAL (int   a) : iDef(a) {}
  11.     DEFVAL (char *a) : cDef(a) {}
  12.     DEFVAL (UBYTE a) : uDef(a) {}
  13. };
  14.  
  15. DEFVAL  defaults[] = {1.0f, 2, "Hello"};
  16.  

 
Nils Pipenbrinck

May 20, 2005, 08:05 AM

Btw.. I just checked.

The compiler (visual c++ whatever) optimizes the c'tors out. A static definition like this does not create any code.

 
Dr. Necessiter

May 20, 2005, 08:50 AM

Very cool... but I must admit to not fully understading the code. I've never used the single colon syntax on those constructors. Is that a method of accessing a perticular union element of the class? I looked in a few books, but didn't turn anything up. If you have a term to search for, that would be great.

Also, I saw you noted that no "code" is generated... that's cool. But do you also mean that the data itself is not duplicated? That's what I'm essentially trying to avoid. I'd like a compeltely static initialization.

 
Betelgeuse

May 20, 2005, 09:12 AM

  1.  
  2.  
  3. class foo
  4. {
  5. public:
  6.    foo(int x);
  7. private:
  8.   int  m_X;
  9. }
  10.  
  11. foo::foo(int x)
  12.   :m_X(x)
  13. {
  14.  // do more stuff here
  15. }
  16.  


This is only possible in the constructor, and is how constructor initializer lists work. It's the preferred method of constructing objects because, well, it's cleaner, and some objects can't be constructed otherwise. For instance, say you had...

  1.  
  2.  
  3. class foo
  4. {
  5. public:
  6.    foo(string &x);
  7. private:
  8.   string &m_X;
  9. }
  10.  
  11. foo::foo(string &x)
  12.   :m_X(x)
  13. {
  14.  // do more stuff here
  15. }
  16.  


how would you otherwise give a value to m_X? It's a reference, so you can only assign it a value at declaration. But it is declarared in the class definition, so it isn't really declared at all.

Furthermore, you can also construct your parent class... e.g. foo is derived from foodaddy... foodaddy has another member m_Y. Now, while foo can assign values to m_Y (if it isn't a reference), it can't construct it, since it belongs to foodaddy. On the other hand, you can construct foodaddy and let foodaddy take care of it...

  1.  
  2. foo::foo(int x)
  3.   :foodaddy(x), m_X(x)
  4. {
  5. }
  6.  


 
Betelgeuse

May 20, 2005, 09:15 AM

Oh I forgot that class, struct, union are all the same semantically except for stuff being public/private and obviously the special behaviour of union. But the syntax and semantics are pretty much the same. Hence you can give a union (which is now a class) a constructor, etc.

 
Nils Pipenbrinck

May 20, 2005, 09:21 AM

the colon syntax works for constructors, it's a initializer list that's sometimes nessesary.. e.g. in the following example:

  1.  
  2.  
  3. class foo
  4. {
  5.   public:
  6.   foo (int a)
  7. };
  8.  
  9. class bar
  10. {
  11.   foo  m_foo;
  12. };
  13.  


In this example you cannot create an instance of bar since foo needs an argument passed in the c'tor. to get around this you use the colon-syntax:

  1.  
  2. class bar
  3. {
  4.   foo  m_foo;
  5. public:
  6.   bar () : m_foo(0) {}; // passes 0 as c'tor argument to foo
  7. };
  8.  


You can do the same to any ordinary type. Writing fDef(a) like the code in the example above just calls the float-constructor with a float as an argument.

You can even use this method to initialize references inside classes (I use this a lot. Since I know it my use of pointers has decreased significantly).

example:
  1.  
  2. class Game
  3. {
  4.   Engine &m_Engine;
  5.   ...
  6. public:
  7.   Game (Engine &a_engine) : m_Engine(a_Engine) {};
  8. };
  9.  


The compiler usually generates *very* compact code for such initializer-lists. In your case even no code at all since the compiler optimizes the stuff out. No data duplication (in release build).

 
This thread contains 7 messages.
 
 
Hosting by Solid Eight Studios, maker of PhotoTangler Collage Maker.