Union

D

David Rasmussen

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?

/David
 
J

JKop

David Rasmussen posted:
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?

/David


struct Data
{
unsigned long a : 8;
unsigned long b : 14;
unsigned long c : 7;
unsigned long d : 3;
};



I've never seen anything like that before! What do the colon and the
number after it do?!

--

Anyways, you'll have to write:

U.data.a = 1;
U.data.b = 2;
 
V

Victor Bazarov

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,166
Messages
2,570,907
Members
47,447
Latest member
TamiLai26

Latest Threads

Top