I have a struct like below:
struct pts_t
{
uint32_t lsb;
uint32_t msb;
};
I would like cast that into a double. Is it safe of directly write:
pts_t t;
double timestamp = t;
and more complex, if the struct type is part of a C dll API, without having "packing" attribute (for all compiler) in that case I have to copy the pts_t*
receive througth the API to pts_t instance i create to control the struct packing ?
void f(pts_t* t)
{
pts_t myt; myt.lsb = t->lsb; myt.msb = t->msb;
double timestamp = *(double*)(&myt.lsb);
}
Even if you assume that your double
are 64 bit wide, if you are looking for portable code you should be really careful with that: your structure and double
might have different alignment constraints and your compiler may get confused because of aliasing rules. A way to avoid problems with that is to use a union
union {
struct pts_t pts;
double timestamp;
} x = { .pts = t };
and then use x.timestamp
.
Also be careful that "composing" double
s like that might result in strange values such as infinities that you wouldn't encounter otherwise.
The initial thought would be to write the following:
double timestamp = *( ( double * ) &( t.lsb ) );
To step through this (assuming you are in a 32-bit environment):
t.lsb
because you need to find the memory address of the first byte in your structure. Note, you can alternatively do &t
.timestamp
uses.Remark:
Now, the three points in the remark blurb are a lot to worry about. It becomes a big pain when porting this code accross multiple platforms. As mentioned below, using C unions
is a much better and correct solution that is portable.
It would be written as follows with C unions
:
double timestamp = ( union { double d; struct pts_t pts; } ) { t } .d;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With