Bored and reading in my favourite room I noticed out of all the c/c++ books I have only one even spends a paragraph talking about unions, and from the little reading here I understand what unions are and what they do... but other than for defining color values that can acces individual channels or the whole color I can't think what they would be good for.
What would you use a union for? Is it just depricated idea? even with the color idea, a class/struct could easily do the same thing and probably better.
What are unions good for?
They allow different interpretation of same memory location.
I know what they do, I was more interested in how they would be used in the real world and why? Just trying to further my knowledge.
Some form of event maybe with an "additional info" variable.
additionalInfo.Int = 10;
additionalInfo.Float = 10.0f
Obviously you can just cast but I believe you can also have type that take a larger number of bytes (such as a double) but use only a bit of it (unsigned int).
additionalIfno.Double = 1.0;
additionalInfo.UnsignedInt = 10;
double takes up more memory than an unsigned int
additionalInfo.Int = 10;
additionalInfo.Float = 10.0f
Obviously you can just cast but I believe you can also have type that take a larger number of bytes (such as a double) but use only a bit of it (unsigned int).
additionalIfno.Double = 1.0;
additionalInfo.UnsignedInt = 10;
double takes up more memory than an unsigned int
Some form of event maybe with an "additional info" variable.
additionalInfo.Int = 10;
additionalInfo.Float = 10.0f
Obviously you can just cast but I believe you can also have type that take a larger number of bytes (such as a double) but use only a bit of it (unsigned int).
additionalIfno.Double = 1.0;
additionalInfo.UnsignedInt = 10;
double takes up more memory than an unsigned int
I believe that is incorrect... the union should take up the space of the largest variable?
You can use unions for handy syntactic sugar purposes. Probably the most useful aspect of unions. For example:
This allows you to use this vector class with XYZW notation, or RGBA, or UVST, which is similar how you can access vector components in vertex/fragment shaders.
Another use of union notation is mapping larger data types over a collection of smaller types. For example,
You can access different parts of the integer without masking. Note that there are pitfalls with this, the mapping order of the array will be architecture dependent. In fact, you can use this type of union to test for machine endian-ness. For example:
You can map float data types across integers, use bit mask manipulation on the integer mapping to modify the float data.
I have used unions in a similar manner to convert exotic 80-bit long double types to 64-bit double using bit manipulation.
It's quite rare when you need to do something like this, and its best to avoid if you can.
class vec4
{
public:
union {float X, U, R;};
union {float Y, V, G;};
union {float Z, S, B;};
union {float W, T, A;};
};
vect4 Colour;
Colour.R = 1.0f; //Same as Colour.X = 1.0f;
Colour.G = 1.0f; //Same as Colour.Y = 1.0f;
Colour.B = 1.0f; //Same as Colour.Z = 1.0f;
Colour.A = 1.0f; //Same as Colour.W = 1.0f;
vect4 Point;
Point.X = 0.123f;
Point.Y = 0.23f;
Point.Z = 0.3f;
Point.W = 1.0f;
//...etc
This allows you to use this vector class with XYZW notation, or RGBA, or UVST, which is similar how you can access vector components in vertex/fragment shaders.
Another use of union notation is mapping larger data types over a collection of smaller types. For example,
union
{
int I;
char C[sizeof(int)];
} Test;
You can access different parts of the integer without masking. Note that there are pitfalls with this, the mapping order of the array will be architecture dependent. In fact, you can use this type of union to test for machine endian-ness. For example:
Test.I = 0x000F;
if (Test.C[0] == 0x0F)
{
//Little endian CPU
}
else
{
//Big endian CPU
}
You can map float data types across integers, use bit mask manipulation on the integer mapping to modify the float data.
union
{
float F;
int32 I;
} Blah;
Blah.F = -1.0f;
Blah.I &= 0x7FFFFFFF; //Clear sign bit (warning: machine dependent operation)
float f = Blah.F; //Should be 1.0f now
I have used unions in a similar manner to convert exotic 80-bit long double types to 64-bit double using bit manipulation.
It's quite rare when you need to do something like this, and its best to avoid if you can.
Isn't using unions in this way undefined behaviour according to the standard? I was told that the standard only supports accessing the element in a union which was last written to, in which case it's only safe to use unions to save space. Combine this with the rules on strict aliasing, and pretty much any form of type pruning relies on compiler specific behaviour.
Are there specific compilers where using unions for type pruning does not work though?
Are there specific compilers where using unions for type pruning does not work though?
I was told that the standard only supports accessing the element in a union which was last written to, in which case it's only safe to use unions to save space. [/quote]
I believe you have point there. Personally I haven't seen any compiler that does not exhibit the behaviour I posted earlier. I dare say, if the bit-field size of each union member is identical, and that their mapping is guaranteed to be at the same physical memory location, then you can expect this behaviour to be consistent. Unless of course there is some kind of data conversion behind the scenes when it's written to memory. I've seen unions used as a crude reinterpret_cast mechanism in C; not exactly 100% safe, but generally they were not a problem if some precautions were taken.
Unions can also help avoid aliasing problems when accessing both different bytes of a multibyte type and the type itself (source: http://locklessinc.com/articles/mutex_cv_futex/ )
Isn't using unions in this way undefined behaviour according to the standard? I was told that the standard only supports accessing the element in a union which was last written to, in which case it's only safe to use unions to save space. Combine this with the rules on strict aliasing, and pretty much any form of type pruning relies on compiler specific behaviour.
Are there specific compilers where using unions for type pruning does not work though?
Yes that and most of what has been posted here is undefined behaviour according to the standard. You really should have an identifier which signals which element is currently stored in the union, then only read this element and none of the others.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement