Trouble casting a struct with bit fields

B

Bob Hairgrove

Surely this is a no-brainer, but sometimes I think I must have no
brain (no comments, please<g>). Anyway, I have the following struct
containing bit fields:

struct ExtPenStyle
{
unsigned long style : 4;
unsigned long : 4; // unused
unsigned long endcap : 2;
unsigned long : 2; // unused
unsigned long join : 2;
unsigned long : 2; // unused
unsigned long type : 1;
unsigned long : 15; // unused
};

I tried casting from/to unsigned long using static_cast,
reinterpret_cast and C-style cast. The compiler refuses to do it, but
I need to call API code which expects an unsigned long with bitmapped
values.

I know I could use a union or memcpy(), but I wonder if there is a
cleaner way? Thanks.

#include <iostream>
#include <ostream>

// struct ExtPenStyle
// { see above };

int main()
{
using std::cout;
using std::endl;

ExtPenStyle xps = ExtPenStyle();
unsigned long ulong(static_cast<unsigned long>(xps));// no good?!?
cout << "Sizeof ExtPenStyle: " << sizeof(ExtPenStyle) << endl;
return 0;
}
 
B

Bob Hairgrove

Try this:
unsigned long ulong(*reinterpret_cast<unsigned long*>(&xps));

Yes, this seems to work. However, I think I will use a union -- it
certainly saves a lot of typing, and seems more intuitive.

Thank you!
 
M

Michiel Salters

Bob Hairgrove said:
Surely this is a no-brainer, but sometimes I think I must have no
brain (no comments, please<g>). Anyway, I have the following struct
containing bit fields:

struct ExtPenStyle
{
unsigned long style : 4;
unsigned long : 4; // unused
unsigned long endcap : 2;
unsigned long : 2; // unused
unsigned long join : 2;
unsigned long : 2; // unused
unsigned long type : 1;
unsigned long : 15; // unused
};

I tried casting from/to unsigned long using static_cast,
reinterpret_cast and C-style cast. The compiler refuses to do it, but
I need to call API code which expects an unsigned long with bitmapped
values.

The compile is right, and the API couldn't care whether you
actually used bitfiels.

E.g.

template< int pos, int length >
struct field {
static unsigned long mask = (1UL<<length-1);
long get( unsigned long src ) { return (src>>pos) & mask }
void set( unsigned long& dest, long val ) {
val &= mask;
dest &= ~(mask<<pos);
dest |= val << pos;
}
};
struct ExtPenStyle
{
unsigned long bits;

field<0, 4> style_pos;
unsigned long get_style_pos() { return style_pos.get(bits); }
void set_style_pos(unsigned long v) { style_pos.set(bits, v); }

//etcetera
};

No casts needed. The compiler will do pretty much the same,
but this is more reliable (there are at least two ways to stuff
bitfields in a long, MSB or LSB first. Here YOU choose.)

HTH,
Michiel Salters
 

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

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top