Sign in to follow this  
Noir

unions

Recommended Posts

I understand that unions are kind of like structs but the members share the same memory. What I don't understand is the practicality of unions. What is their use? For example, when would I be concerned with accessing information like this:

#include <iostream>
using namespace std;

union MyUnion
{
	long allbytes;
	struct tagpart
	{
		char byte1;
		char byte2;
		char byte3;
		char byte4;
	}part;
};

int main(int argc, int argv[])
{
	MyUnion m;
	m.part.byte1 = 'a';
	m.part.byte2 = 'b';
	m.part.byte3 = 'c';
	m.part.byte4 = 'd';
	cout << m.allbytes << "\n";
	cout << m.part.byte1 << "\n";
	cout << m.part.byte2 << "\n";
	cout << m.part.byte3 << "\n";
	cout << m.part.byte4 << "\n";
	return 0;
}


Whenever I change one member of the union, all members change and I just don't see the reasoning for including this functionality in C/C++. Its probably simple and I'm just too n00b to see it. =P

Share this post


Link to post
Share on other sites
Say you have a matrix structure you could use a union to give two different ways to access it. You can access it via ._11 or via m_indices[0][0].


union
{
struct
{
float _11, _12, _13, _14,
_21, _22, _23, _24,
_31, _32, _33, _34,
_41, _42, _43, _44;
};

float m_indices[4][4];
};

Share this post


Link to post
Share on other sites
Unions has two primary uses.

1. Variants, store different kinds of data in the same structure depending on it's state.
struct variant {
enum {
CHAR,
INTEGER
FLOAT,
DOUBLE,
POINTER
} type;

union {
char c;
int i;
float f;
double d;
void *p;
} data;
};
2. Accessing the same data in different ways depending on the context.
union pixel {
u32 packed;
struct {
u8 r, g, b, a;
} components;
};

Share this post


Link to post
Share on other sites
Well, for example you could use it in a vector class...
That way you could both have access to the vector in array form, and as xyz form..

class CMyVec
{
public:
union
{
float arr[3];
float x,y,z;
};
};


It was some time since i looked at unions, so pardon me if the code isn't correct...it should be enough to show one area of usage though.

EDIT: Argh, heavily beaten [grin]

Share this post


Link to post
Share on other sites
a union can still exist to offer most of the struct functionality, constructor/destructor methods, static members... etc...

take a look at the following example:

#include <iostream>

union error
{
int i;
struct
{
unsigned short code;
unsigned priority : 2; // 00 is normal, 01 is low, 10 is high, 11 is extreme...
unsigned warning : 1; // 1 means this is just a warning, not a real error...
};

static int ii; // errors counter

error(int _i = 0): i(_i) { ii++; }
operator int() { return this->i; }
bool is_warning() { if( this->priority ) return true; return false; }

static error system_error(){ error r; r.code = 10; r.priority = 0x2; return r; }
};

int error::ii = 0;

int main()
{
error e;
e.i = 5; // wil affect everything...
e.code = 10; // wont affect other things...
e.is_warning(); // will return the warning state :)

std::cout << (int)e << std::endl;
std::cout << (int)error::system_error() << std::endl;
std::cout << error::ii << std::endl;
}




/widen your imagination.

Share this post


Link to post
Share on other sites
Unions are used when a data structure might contain distinct, but mutually-exclusive, pieces of data, and you want to make efficient use of the space. So you would have a union member in your data structure, along with a tag indicating which 'version' of the union you are actually using.

Their usage as an utter subversion of C's already ailing type system (what most of the other posters have demonstrated) is completely incidental and absolutely non-portable. You should only consider that one union member is valid at any given time.

Share this post


Link to post
Share on other sites
Quote:
Original post by Fruny
completely incidental and absolutely non-portable


Non-portable? True, specifically if you switch to another platform with a different endianness or char-size.

Incidental? False, a union is defined as a struct in which each member has the same address (10.4.12 in my [Dutch] translation of TC++PL). That is pretty well-defined behaviour fitting the uses given above. Of course, if you were to use something other than simple types, things go pear-shaped.

Share this post


Link to post
Share on other sites
Quote:
Original post by Kippesoep
Non-portable? True, specifically if you switch to another platform with a different endianness or char-size.
It's portable if you're considering the members to be mutually-exclusive, as someone mentioned above. Using unions as means to access the same data in different ways is misusing the construct, and of course, its non-portable.

Look at SDL's event structures. Best example of unions i've seen, highly practical and portable.

Share this post


Link to post
Share on other sites
Quote:
Original post by Fruny
Their usage as an utter subversion of C's already ailing type system (what most of the other posters have demonstrated) is completely incidental and absolutely non-portable. You should only consider that one union member is valid at any given time.
I wouldn't call it completely incidental. While it's use is unportable it was definetly intended and a mere byte order switch should be enough to fix it. Sure, there's probably some ancient system or DSP around where it won't work, but that doesn't prevent it from working in practice on just about all of the platforms targetted in this forum. And if it doesn't hold true you almost certainly know about it's limitations anyway.
C89 still supports 6-character linking and one's complement integers, are you willing to sacrifice those assumptions too in the name of portability?
Just don't ignore a nice convenience like this just because it might not always work, spend your time investigating how the platforms you're targetting actually handle this feature instead. The line will have to be drawn somewhere anyway..

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this