How to convert floating-point to unsigned variable?
Could someone please help me with byte ordering regarding floating point variables? Actually the code is working correctly on Solaris, but not on Windows Xp. Here is a piece example of my code: ....
int x_snd=1;
float y_snd=1.13;
struct {
int xx_snd;
float yy_snd;
} data_snd;
int x_rec;
float y_rec;
struct {
int xx_re开发者_StackOverflow中文版c;
float yy_rec;
} data_rec;
//marshalling
data_snd.xx_snd=htons(x_snd);
data_snd.yy_snd=htonl(*(int*) &y_snd);
//write data to socket
send(sock1, &data_snd, ...
//clean ...
//read data from socket
if recv(sock, &data_rec ...
//unmarshalling
x_rec=ntohs(data_rec.xx_rec);
y_rec= *(float*) &(ntohl(data_rec.yy_rec));
...
Th code was compiled with gcc on Unix and with MSVC++6 on wndows. Any of your help would be very appreciated and I would be glad if you could direct me to any link or document that gives usefull information about endianness ...
Thanking you in advance for your help, mk
There's a lot more potential variety and issues in floating point formats than just the endian problem you have to deal with when marshalling and unmarshalling integers.
One way out is to format floating point numbers as text, using printf
, and reading them back with strtof()
(as bmargulies indicated).
Another way that will work as long as the machines share the same FLT_RADIX
value, is to break them into a mantissa and exponent value:
#include <math.h>
#include <limits.h>
float x = 1.13;
int x_exp;
long x_mant;
x_exp = ilogbf(x);
x_mant = (scalbnf(fabsf(x), -x_exp) - 1) * LONG_MAX;
if (x < 0.0)
x_mant = -x_mant;
You then have an int
and a long
(x_exp
and x_mant
from the above code) to put onto the wire, which you can use the normal ntohl()
and htonl()
functions to do. To convert these back into a float
, use:
x = scalbnf((fabsf(x_mant) / LONG_MAX) + 1, x_exp);
if (x_mant < 0)
x = -x;
Note that most machines have a FLT_RADIX
value (defined in float.h
) of 2, so if you check for that during compilation and abort if it's something else, you should be reasonably portable.
This is a generally bad idea. The format of floating point numbers isn't necessarily the same on different hardware, even after accounting for byte order. I would have to recommend shipping them here and there as strings.
Assuming both systems have the same floating point format, yy_rec
is a float
; ntohl
takes an unsigned long
; the floating point value, potentially with incorrect endianness, is being converted to an integer representation when it is passed into ntohl
.
You should be getting a compiler warning due to the conversion from float
to unsigned long
.
精彩评论