Reputation: 459
How can I find information about float
datatype in C? I mean the bit struct for this type (decimal, signal indicator, etc...)?
Let me explain what I'm trying to do:
I am implementing an network protocol and I need to send 6 octects with Latitude and Longitude (according to protocol documentation). First 3 octects must have LAT information and last 3 must have LON information.
I can't use bitwise operators in float
datatype, so for debug, I'm copying memory of float
variable to a new uint32_t
variable (both 4-bytes wide) and then, trying to shift bit's to get the correct value, but it's not working.
This is the code that I'm using to test/debug conversion:
int32_t b = 0;
memcpy(&b,&a,4);
int32_t c = (b >> 23);
printf("Valor de C: 0x%X, Decimal: %d\n",c,c);
// Should print only '23', but it's printing
// Valor de C: 0x41B, Decimal: 1051
After 'knowing' the correct bit-position of float, I'll copy those bit's to my protocol data, which is an array of unsigned char[6] (this I can't change the type, only values).
Any tip's about how to accomplish this?
Upvotes: 0
Views: 595
Reputation: 3333
Here is a sample code showing how to encode the float latitude. (same thing for longitude). See: https://en.wikipedia.org/wiki/Q_(number_format)#Float_to_Q for an introduction to fixed point encoding with 2 complements sign management.
It uses fixed point encoding with weight provided by the specification.
#include <stdio.h>
#include <stdlib.h>
int main()
{
/* weight of one bit */
const float weight = 180./(1 << 23);
printf ("w=%f\n",weight);
/* a few sample conversions */
/* 2.53 degres */
float lat = 2.53;
printf ("lat=%f\n",lat);
int fp_lat = (int) (0.5f + lat / weight);
printf ("fplat=0x%x\n",fp_lat);
lat = 180.f; /* +180 degres */
printf ("lat=%f\n",lat);
fp_lat = (int) (0.5f+ lat / weight);
printf ("fplat=0x%6x\n",fp_lat); /*exactly 23 bits */
/* negative numbers)*/
lat = -180.f; /* -180 degres */
printf ("lat=%f\n",lat);
fp_lat = (int) (0.5f + abs(lat) / weight);
if (lat <0)
{
/*2 complement representation */
fp_lat = (~fp_lat + 1) & 0xffffff;
}
printf ("fplat=0x%6x\n",fp_lat); /* same value as 180 */
/*sample packing for latitude */
unsigned char msg[6];
msg[0] = (unsigned char)((fp_lat >> 16) & 0xff); /* most significant byte of 24 bits*/
msg[1] = (unsigned char)((fp_lat >> 8 ) & 0xff);
msg[2] = (unsigned char)((fp_lat ) & 0xff);
/* to be continued */
return 0;
}
Upvotes: 2
Reputation: 141523
The interpretation of data is something separate from the data. The unit of the data is something separate from the data itself. So I can say 123 milliseconds
or 0.123 seconds
or 234 half-milliseconds
or 1.23 * 10^-2 seconds
and all these forms represent the same "value".
The data you posted I guess is composed of two numbers encoded in twos-complement numbers represented in big endian with most significant bit first.
unsigned char data[6]; // assuming indexes reference octet numbers
// big endian - first byte is the most significant
// I assume the hardware uses twos complement internally
// the method as described in https://stackoverflow.com/questions/35876000/converting-24-bit-integer-2s-complement-to-32-bit-integer-in-c
int32_t latitude_value = (int32_t)( data[0] << 24 | data[1] << 16 | data[2] << 8 ) / 256;
// latitude_value represents latitude in units of 180/2^23 degrees
Now you can "transform" the latitute from units of 180/2^23 degrees
to units of plain degrees
if you want to represent it that way:
double latitue_in_degrees = (double)latitude * 180.0 / exp2(23);
Note that there are problems with floating point types.
What is the struct (binary format) of float datatype in C?
How can I find information about float datatype in C?
I mean the bit struct for this type (decimal, signal indicator, etc...)?
The exact format of float
type depends on your compiler - it can be anything. Well, an overwhelming majority of systems/compilers today use binary32
format from IEC 754 standard for float
datatype. Refer to the standard and endless net resources for the exact format of the datatype. For example this converter is just fun to use.
Upvotes: 1
Reputation: 164
Usually for such purposes bit fields are used. You can try something like this:
#pragma pack(1)
typedef struct {
union latitude{
uint32_t value : 24;
struct octets{
uint8_t octetOne : 8;
uint8_t octetTwo : 8;
uint8_t octetThree : 8;
}
}
union longitude{
uint32_t value : 24;
struct octets{
uint8_t octetOne : 8;
uint8_t octetTwo : 8;
uint8_t octetThree : 8;
}
}
} frame;
Then store incomming data in this struct and access desired values by:
frame.longitude.value
etc.
Upvotes: -1