type cast problem

H

hamze

hi,
I have some double precision numbers ( 64bit) which should be
transmitted and received via two FIFOs.
for example like below;

double d1, d2;
d1 = 3.2
send(d1);
d2 = receive(d2);



but my FIFOs are 32bit not 64bit so I must break double number before
send or concatenate them after reception. gcc compiler prohibit me to
break a 64 bit double to two 32 bit integesrs by below lines

first 32 bit : * ( (int *) ( &d_num) )
last 32 bit : * ( (int *) ( &d_num) +1 )

because it says that cast between double and int pointer is not
allowed. then I use void * :

first 32 bit : * ( (int *) (void *) ( & d_num ) )
last 32 bit : * ( (int *) (void *) ( & d_num ) +1 )

I used this way to break a double number for sending and also give
value to a double number which is received.

Now problem is :
when I turn compiler optimization ON there are some strange
problems!,
after debugging assembly code I understood that compiler can not
understand CHANGE or USAGE of a double variable by above lines, so
optimization mix up my code.
how can I solve this problem in an efficient way?
 
B

Balog Pal

hamze said:
I have some double precision numbers ( 64bit) which should be
transmitted and received via two FIFOs.
for example like below;

double d1, d2;
d1 = 3.2
send(d1);
d2 = receive(d2);



but my FIFOs are 32bit not 64bit so I must break double number before
send or concatenate them after reception. gcc compiler prohibit me to
break a 64 bit double to two 32 bit integesrs by below lines

first 32 bit : * ( (int *) ( &d_num) )
last 32 bit : * ( (int *) ( &d_num) +1 )

This puts you in the "undefined behavior" land. What in practice means it
may work with desired results on some platforms/compilers/switches, with bad
results on others and causing stuss like BUS ERROR (core dumped) on yet
others.

C++ (or C) is not assembly despite working close, and if you want to cheat
with the type systems you shall look for additional guarantees. Which may or
may not be present.

What you do have in the standard is: you may cast the pointer to a different
type, and hold it, eventually cast back to its original type, and then
dereference to access to original object.

Beyond that you may cast your pointer to unsigned char * and access the
bytes. Or use memcpy. Do one of those.

In practice another method is to use union for "conversion". It has better
chance to work than raw casts. The base rules are strict there too, but many
compilers support conversion that way as extension.
 
A

Asger-P

Hi hamze

hi,
I have some double precision numbers ( 64bit) which should be
transmitted and received via two FIFOs.
for example like below;

double d1, d2;
d1 = 3.2
send(d1);
d2 = receive(d2);

I am no expert, but couldn't You use something like this:

struct NumberSplit
{
union{
struct{
__int32 i1;
__int32 i2;
};
struct{
double d;
};
};
};

NumberSplit Ns;
Ns.d = 3.2;

send(Ns.i1);
send(Ns.i2);

Then just go the other way in the other end.

P.s. Do consider little and big endian if You need to.

Best regards
Asger-P
 
E

Edek

hi,
I have some double precision numbers ( 64bit) which should be
transmitted and received via two FIFOs.
for example like below;

double d1, d2;
d1 = 3.2
send(d1);
d2 = receive(d2);



but my FIFOs are 32bit not 64bit so I must break double number before
send or concatenate them after reception. gcc compiler prohibit me to
break a 64 bit double to two 32 bit integesrs by below lines

first 32 bit : * ( (int *) (&d_num) )
last 32 bit : * ( (int *) (&d_num) +1 )

I never know, which pointer type this "+1" refers to. I would use
parentheses to make sure you offset by 1*sizeof(int).

In general, you need to do some reinterpret_cast.

One mentioned unions: that's reasonable.

The main problem once you have casting is strict aliasing. Breaking
the rules will result in optimisations failing now and then.

The only safe cast (by the standard) is casting the double* to char*.
Char is in this regard a special case, other than other types.
Unions should be safe too, but that's not what the standard says.
Then you need to construct int32_t (or better uint32_t) values
from the 8 char's paying attention to byte order and char overflow.

Do not worry about bit shifts ruining performance: they will get
optimised away; it's just some typing.

My gcc has the following defines (built-in), which help determine the
byte order:

#define __ORDER_LITTLE_ENDIAN__ 1234
#define __ORDER_BIG_ENDIAN__ 4321
#define __ORDER_PDP_ENDIAN__ 3412
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
#define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__


because it says that cast between double and int pointer is not
allowed. then I use void * :

first 32 bit : * ( (int *) (void *) (& d_num ) )
last 32 bit : * ( (int *) (void *) (& d_num ) +1 )

I used this way to break a double number for sending and also give
value to a double number which is received.

Now problem is :
when I turn compiler optimization ON there are some strange
problems!,
after debugging assembly code I understood that compiler can not
understand CHANGE or USAGE of a double variable by above lines, so
optimization mix up my code.
how can I solve this problem in an efficient way?

Like above. On the other side of pipe you need to do the opposite.

Since you did not say, and I do not know these bits,
if the pipe on the other end has some other representation of doubles,
it will fail. This solution will effectively copy the bytes, at most
adjusting their order.

HTH
Edek
 
R

refigh

thanks for your helps

I used char * instead of void * like below ( a part of code) :

char * a_adr = (char *)(&a);
char * b_adr = (char *)(&b);
char * c_adr = (char *)(&c);


write_into_fsl( cmd , 0);
write_into_fsl(*( (unsigned int *)a_adr ) , 0);
write_into_fsl(*( ((unsigned int *)a_adr) + 1) , 0);
write_into_fsl(*( (unsigned int *)b_adr ) , 0);
write_into_fsl(*( ((unsigned int *)b_adr) + 1) , 0);
read_from_fsl(*( ((unsigned int *)c_adr) + 1) , 0);
read_from_fsl(*( (unsigned int *)c_adr ) , 0);
read_from_fsl( status , 0);

but again when optimization turned ON, compiler did not understand
USAGE of variable a and b and also did not understand that new value
is assigned to variable c.
 
R

refigh

I think problem solved simply by using unions! :)

union id_union{
double d;
int i[2];
};


id_union au, bu, cu;

au.d = a;
bu.d = b;


write_into_fsl( cmd , 0);
write_into_fsl( au.i[0] , 0);
write_into_fsl( au.i[1] , 0);
write_into_fsl( bu.i[0] , 0);
write_into_fsl( bu.i[1] , 0);
read_from_fsl( cu.i[1] , 0);
read_from_fsl( cu.i[0] , 0);
read_from_fsl( status , 0);

c = cu.d;


thanks a lot for your helps :)
 

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
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top