Bit manipulation question

  • Thread starter Bartholomew Simpson
  • Start date
B

Bartholomew Simpson

I need to pack two small values into a double data type.

I have come up with the following struct, which only takes up 16 bits
and can therefore be stored safely in a double.

struct mytype_
{
unsigned char fld1: 4,
fld2: 12;
};


My question though is how do I assign a value of type mytype to a double
(and back from a double)?


struct mytype_ snoopy ;
double foobar ;

snoopy.fld1 = 2;
snoopy.fld2 = 256 ;

//Are these legal (i.e. will they behave as expected - display value
semantics behaviour)?
foobar = snoopy ;
snoopy = foobar ;
 
J

John Harrison

Bartholomew said:
I need to pack two small values into a double data type.

I have come up with the following struct, which only takes up 16 bits
and can therefore be stored safely in a double.

struct mytype_
{
unsigned char fld1: 4,
fld2: 12;
};


My question though is how do I assign a value of type mytype to a double
(and back from a double)?


struct mytype_ snoopy ;
double foobar ;

snoopy.fld1 = 2;
snoopy.fld2 = 256 ;

//Are these legal (i.e. will they behave as expected - display value
semantics behaviour)?
foobar = snoopy ;
snoopy = foobar ;


Your code is not legal (no surprise). I guess the only way to do this is
to use a union

struct mytype_
{
unsigned char fld1:4, fld2:12;
};

union wierd
{
double d;
mytype m;
};

snoopy.fld1 = 2;
snoopy.fld2 = 256;
wierd foobar;
foobar.m = snoopy;
snoopy = foobar.m;

Use foobar.d to get the double value. Although what value it will be is
anyone's guess.

john
 
J

James Kanze

Not sure I understand this. On most machines, the maximum size
of a character bit field will be 8.
Your code is not legal (no surprise). I guess the only way to do this is
to use a union
struct mytype_
{
unsigned char fld1:4, fld2:12;
};
union wierd
{
double d;
mytype m;
};
snoopy.fld1 = 2;
snoopy.fld2 = 256;
wierd foobar;
foobar.m = snoopy;
snoopy = foobar.m;
Use foobar.d to get the double value.

Use foobar.d and get undefined behavior, you mean.

The only way to legally do what he wants is to find an
expression which uniquely specifies the two values, and will
always result in a value which is exactly representable in a
double. Since his code suggests that the values are in the
range 0...15 and 0...4095, something like:

double d = 16.0 * fld2 + fld1 ;

would do the trick, with:

int fld1 = (int)d % 16 ;
int fld2 = (int)( d / 16 ) ;

to read them.
Although what value it will be is anyone's guess.

A signaling NaN?
 
J

John Harrison

James said:
Not sure I understand this. On most machines, the maximum size
of a character bit field will be 8.

The number of bits in a bit field can be larger than the number of bits
in the type. The extra bits are padding bits, in some implementation
defined manner.
Use foobar.d and get undefined behavior, you mean.

The only way to legally do what he wants is to find an
expression which uniquely specifies the two values, and will
always result in a value which is exactly representable in a
double. Since his code suggests that the values are in the
range 0...15 and 0...4095, something like:

double d = 16.0 * fld2 + fld1 ;

would do the trick, with:

int fld1 = (int)d % 16 ;
int fld2 = (int)( d / 16 ) ;

to read them.


A signaling NaN?

The only problem with your solution is that it doesn't involve bit
manipulation (as mentioned in the title of this thread). My assumption
was that the OP wanted to directily manipulate the bits of a floating
point number and was smart enough to put the correct bits in the correct
places.

But as you say, in terms of standard C++, my suggestion is undefined
behaviour.

john
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,151
Latest member
JaclynMarl
Top