Advertisement

Question on C++ 'union'

Started by August 14, 2000 04:01 PM
10 comments, last by Lord Chaos 24 years, 4 months ago
Is it possible to have a union with this functionality:
    
class foo
{
  public:
    
    union
    {
      int iArr[4];
      int a,b,c,d;
    };
};
    
where the a, b, c and d variables ''map'' to iArr[0] to iArr[3], so if I access foo::c it will be the same as foo::iArr[2]? And if so, how to I declare that union? (the above example won''t work, since all of them (a to d) will ''map'' to iArr[0]. I couldn''t find my copy of "The C++ Language" so... well, I hope you can either help me or tell me it can''t be done that way. Need to know
-------------------------------------------------------------LGPL 3D engine - http://www.sourceforge.net/projects/realityengine
Hi there,

the fact that a, b, c and d map to the first element of the array is the way a union behaves. Every variable in the union is adressed at the start of the union and the union is the size of the biggest variable in it.

But wait a minute, maybe this can be used to trick the compiler.

How about this: (first try).

        union{   int iArr[4];         struct   {      int a,b,c,d;   } otherVariables;}/*( It seems like this forum board only allows one code box per message so I'll type the rest in here)The above will probably work but you would have to acces the variables like:foo::othervariables.cwhich is probably not what you want.Next try:don't use Unions. Do this:*/   int iArr[4];         int& a = iArr;   int& b = &iArr[ 1 ];   int& c = &iArr[ 2 ];   int& d = &iArr[ 3 ];/*This will probably work, but you don't want this, cause you are wasting 4 int references (16 bytes) purely on references, which is nonsense since you have these variables anyway.I more and more start to wonder why you need this functionality... <img src="smile.gif" width=15 height=15 align=middle>It sure as h*ll is a funny puzzle!!!!Let's try something else (I'm getting enthousiastic now <img src="smile.gif" width=15 height=15 align=middle> hehe).How about this one : )this one is funny.I just read in the MSDN that unions can have methods.*/union{    int iArr[4];    int a( void ) { return iArr[ 0 ]; }    int b( void ) { return iArr[ 1 ]; }    int c( void ) { return iArr[ 2 ]; }    int d( void ) { return iArr[ 3 ]; }}    


But then you would have to acces them like
foo::a() (notice the brackets) because they are
methods which is not something you want.

Shit man!! haha, this is getting better
everytime.

Let me see.

Shit man, I give up. I'm sorry. I looked into
bitfields but they can't help you either.

Goodluck and keep us updated on any constructions
you think of.

Jaap Suter

p.s. Somebody is going to come up with
the correct construction in 5 minutes which
is so incredibly easy that it makes me look
very very stupid indeed, trying to think of
all the above complex workarounds. But then again, I
sure had lots of fun thinking it over. Best posts since
months!!!

Edited by - s9801758 on August 14, 2000 5:39:26 PM
____________________________Mmmm, I''ll have to think of one.
Advertisement
Not the way you''ve shown here. a, b, c, and d will all share memory space with iArr[0].

This is a possible solution:
class foo{public:  int iArr[4];  int &a, &b, &c, &d  foo () : a (iArr[0]), b (iArr[1]), c (iArr[2]), d (iArr[3]) {}}; 


You might also try this:
class foo{public:  union  {    int iArr[4];    struct    {      int a, b, c, d;    };  };}; 


(note, I usually never post code without trying it, but I''m just too busy right now. I look forward to the flames if one of these methods don''t work.)
quote: Original post by Lord Chaos

Is it possible to have a union with this functionality:

        class foo{  public:        union    {      int iArr[4];      int a,b,c,d;    };};        


where the a, b, c and d variables ''map'' to iArr[0] to iArr[3], so if I access foo::c it will be the same as foo::iArr[2]? And if so, how to I declare that union? (the above example won''t work, since all of them (a to d) will ''map'' to iArr[0].

I couldn''t find my copy of "The C++ Language" so... well, I hope you can either help me or tell me it can''t be done that way. Need to know



My guess is that this might work but be unreliable, depending on whether you''re on a big-endian or little-endian system.


class foo{  public:            union        {              int iArr[4];              int a,b,c,d;        };};     


quote:
where the a, b, c and d variables ''map'' to iArr[0] to iArr[3], so if I access foo::c it will be the same as foo::iArr[2]? And if so, how to I declare that union? (the above example won''t work, since all of them (a to d) will ''map'' to iArr[0].


The above will not work that way. The reason for it is that each integer variable of a,b,c,d actually share the same memory space. So, a=b=c=d.

You need to take one of the other suggestions and put it into a structure to get access to the individual interger variables.

If you really need to do this, then use

    union{   int iArray[4];   struct    {      int a;      int b;      int c;      int d;   } sArrayElements;};    


Maybe if you tell us what you are trying to accomplish? What you need to do? We might come up with a better alternative.

Alek



Really, I want'' trying to accomplish anything Just wanted to know if it was possible... Once I thought about it for a while, I had an idea that it might be useful in (for example) a class representing a 3D vector:

    class Vector3d{  protected:        union    {      float fComponents[4];            //Yes, I know this doesn''t work, as      //I wrote in my first post, but you      //understand what I want to do :-)      float x,y,z,w;    };  public:    //Some junk here};    


But then I realized it wasn''t as useful as I first thought, unless it was possible to do like this:

Vector3d arr[10];float *pArr = (float*)arr;//Then to access the y component of the 6:th vectorfloat y = pArr[ 5 * 4 + 1 ];


-------------------------------------------------------------LGPL 3D engine - http://www.sourceforge.net/projects/realityengine
Advertisement
The anser was there, staring me straight in the eye in one of the above posts. And I was too stupid to notice it

Anyway, this works exactly as I want it (with use of a nameless struct).

    class foo{  public:    union    {      float arr[4];      struct      {        float a,b,c,d;      };    };    foo() {}    ~foo() {}};    


To access the third element in the array, one can use both these:

foo bar;bar.arr[2] = 1.0f;bar.b = 1.0f;


Thanks everyone for all interesting ideas!

One questions though... if I want to make sure the above union only occupies sizeof(float)*4 bytes of memory, do I need to use some #pragma directives? (I''m using VC++ and have struct member alignment set to 8 bytes)
-------------------------------------------------------------LGPL 3D engine - http://www.sourceforge.net/projects/realityengine
Also, it actually worked to do like this (the same class foo as above):

foo arr[10];float *pArr = (float*)arr;pArr[2*4 + 2] = 2.0f;


to access the arr[2].c element. Then to my (hopefully last) questions:

Is this guaranteed to work on all compilers? Or do I need (as asked above) to make sure the union in class foo only occupies sizeof(float)*4 bytes of memory.
-------------------------------------------------------------LGPL 3D engine - http://www.sourceforge.net/projects/realityengine
It is cool for vectors, because you can do this, making a single vec be accessible by x,y,z, or r,g,b, or pitch yaw roll, or [1],[2],[3], depending on what it''s being used as.

    template <class t_Cls>class CVec3{	public :		union 		{			t_Cls m_xyz[3];			union {				struct { t_Cls x; t_Cls y; t_Cls z; };				struct { t_Cls r; t_Cls g; t_Cls b; };				struct { t_Cls pitch; t_Cls yaw; t_Cls roll; };			};		};// .. etc};    
Nice idea

What I had in mind from the start was something like this (well, the union part is not really needed, but a nice touch )

    #pragma pack( push, 1 )class Vector3d{  public:    union    {      float fComponents[3];      struct      {        float x,y,z;      };    };    //Example operator    Vector3d operator %( const Vector3d &v1, const Vector3d &v2);};#pramga pack( pop )//Array of vector components in x,y,z,x,y,z.... orderfloat fVectorArray[100*3];Vector3d crossProd = *((Vector3d*)&fVectorArray[19*3]) % *((Vector3d*)&fVectorArray[20*3]);    


Not a very good-looking example, but hey - you get the point
-------------------------------------------------------------LGPL 3D engine - http://www.sourceforge.net/projects/realityengine

This topic is closed to new replies.

Advertisement