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" doubles 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