David Rasmussen said:
I have some data packed in by bitfields:
struct Data
{
unsigned long a : 8;
unsigned long b : 14;
unsigned long c : 7;
unsigned long d : 3;
};
I want to be able to easily address and move etc. the underlying
unsigned long that these are packed into. Something like
union U
{
Data data;
unsinged long ul;
};
U u;
u.a = ...;
u.b = ....;
unsigned long x = u.ul;
Is there an easier way to achieve this?
Add a conversion operator to the structure.
struct Data
{
...
operator unsigned long() const
{
// do what you need to do
}
};
...
Data data;
data.a = ...
data.b = ...
unsigned long x = data;
Of course the "what you need to do" can be as simple as forming
a union and returning the value of the 'ul', or it could be
something different (in case you need it). The simple thing:
...
operator unsigned long() const
{
union { Data d; unsigned long ul; } u = { *this };
return u.ul;
}
Although, and we discussed it in comp.std.c++ at some point, C++
does NOT guarantee the validity of such operation. The union exists
not to convert the same data representations from one type to another
but to save memory. The Standard is written so that you can only
extract from a union what you put in it. In your case, if you put
(assign or initialise) a Data in the union, you are not guaranteed
to get the "underlying unsigned long" from the other member. I could
recommend using reinterpret_cast:
Data data;
data.a = ...
data.b = ...
unsigned long ul = *reinterpret_cast<unsigned long*>(&data);
but that's not guaranteed by the Standard either (though some would
argue that "it does what we need").
The only guaranteed way is to write your conversion operator this way:
operator unsigned long() const
{
return a + (b << 8) + (c << 22) + (d << 29);
}
and then you can get the correct value (if that's the layout you
designed it to be).
Victor