Parse four bytes to floating-point in C - c

How do I take four received data bytes and assemble them into a floating-point number?
Right now I have the bytes stored in an array, which would be, received_data[1] ... received_data[4]. I would like to store these four bytes as a single 32-bit single precision float.
-Thanks
I'm actually receiving a packet with 19 bytes in it and assembling two sets of four bytes to make two floating-point numbers. So received_data[1] to received_data[4] is one float, and received_data[5] to received_data[8] is the other...
*UPDATE:**** **More Info...
The first bit, or the sign bit of the float, is the seventh bit the the first byte, here's what I did to check...
#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
if( CHECK_BIT(received_data[1], 7)) //set or clear LED2
{LATAbits.LATA2=1;}else{LATAbits.LATA2=0;}
if( CHECK_BIT(received_data[5], 7)) //set or clear LED3
{LATAbits.LATA3=1;}else{LATAbits.LATA3=0;}
I then checked this by sending alternating positive and negative numbers from my data source, which should have changed the LED's accordingly and it worked.
As long as all that holds true, that means the bytes are in the right order, but they are stored little-endian, correct? Will this be stored into the float in the right order? I haven't had any luck parsing the bytes and reading it as a float yet...
If anyone has any experience with it, I'm using the C18 MPLAB IDE compiler.
FINAL UPDATE:
I have my application running! Just some minor bug fixes now!
THANKS!
Thanks for all the help guys! I'm new to stackoverflow, but this community on here is truly awesome! And a tool like this is truly priceless! I can not even begin to tell you how much time and frustration you have all saved me!

You need to be sure the byte order is correct. Either
float f1 = *(float*)(received_data+1)
float f2 = *(float*)(received_data+5)
or if you have to reverse the bytes, you'll have to copy, so here's an alternative:
union {
char chars[4];
float f;
} u;
for (i = 0; i < 4; i++)
u.chars[3-i] = received_data[i+1];
float f1 = u.f;
// ... and similarly for second float
It had better be the case that these bytes were written by something like the inverse of this process (either you took the address of a float and cast it to char * or you had a union of char[4] and `float'.)

How about just copying the data via memcpy?
inline float FloatFromByteArray (const unsigned char * received_data)
{
float f;
memcpy (&f, received_data, sizeof (float));
return f;
}
It copies the data starting at received_data[0]. If you want to copy from received_data[1] just add the offset inside memcpy.
inline float FloatFromByteArray (const unsigned char * received_data)
{
float f;
memcpy (&f, received_data+1, sizeof (float));
return f;
}

You could assemble them in an order that depends on the endianness of your machine, then cast to a float*, and use that pointer to access them.
You would usually but the also put them in data[0]...data[3]. So...
char *data;
//Assemble in the *right* order
data[0] = received_data[4]; // index is machine dependant!
...
// cast
float *fptr = (float *)data;
printf ("%f\n",*fptr);
From your edit, perhap you should just dump this stuff into a struct:
struct packet_s {
char byte0;
float f1;
float f2;
...
}
Then just read (2) or whatever directly into the struct. This method has been discussed on SO before. For instance:
How to get data out of network packet data in Java is closely related

This is how I buffer a float:
static char* bufferFloat (int* bLen, float value) {
*bLen = sizeof(float);
char* buf = malloc (*bLen);
int storage;
memcpy (&storage, &value, sizeof (int));
uint32_t val = htonl (storage);
memcpy (buf, &val, *bLen);
return buf;
}
This is how I receive a float:
static float readFloat (char* buf, int* bLen) {
float ret;
int temp;
if (*bLen < sizeof (float)) {
*bLen = 0;
return 0.0f;
}
memcpy (&temp, buf, sizeof (int));
uint32_t val = htonl(temp);
memcpy (&ret, &val, sizeof (float));
*bLen = sizeof (float);
return ret;
}
This is apart of some hobby networking code i wrote. I hope it helps and it seems to work perfectly for me. :D
Actually, if you want that networking code go here: http://cgi.cse.unsw.edu.au/~robertm/myProjects.php
and find the right project.

Assuming they're of the right format already:
float f = *((float*)(&received_data[1]));
Make sure you don't mean received_data[0]. I've left it as one in case you have a filler byte.

Related

Converting any variable from big to little endian - how to avoid void pointers?

I'm working on an application that needs to convert any type of the variable from big to little-endian.
My system works with different variable types (16, 32, and 64 bits wide), and I need to be able to change the endianness with a single function. I wrote a function that manages to swap bytes in any variable however, I'm not happy with it. It works, but it requires dereferencing void pointers, which are prone to error with the double star...
Is there any better way to approach the problem?
Is there any way to avoid void pointers as return value? I was thinking about switch-case loop (eg. case 4 bytes -> return int32) however, I don't know how to write a function prototype for a function that returns different values.
My function:
void* swapBytes(void* number, int bytes_num){
void* swapped;
unsigned __int8* single_byte_ptr;
swapped = malloc(bytes_num * sizeof(__int8));
for (int i = 0; i<bytes_num; i++){
single_byte_ptr =((unsigned __int8*)number)+i; //get current byte
*( (__int8*)(swapped)+((bytes_num-1)-i)) = (unsigned __int8)*single_byte_ptr; //save the byte in new position
}
return swapped;
}
the way I call this function
__int64 big_number = 35169804487071;
big_number = *(__int64*)(swapBytes(&big_number, 8));
One problem you have is that you're leaking memory. You return a pointer to malloc'ed memory, but you're not saving the pointer when you return.
Given that you're assigning the result back to the same value, you're better off updating the existing variable, swapping the current byte with a byte on the "opposite" side.
You also don't need to use a void * anyplace other than the parameter type. Inside of the function, just use a pointer to an unsigned char or unsigned __int8 to work through the bytes.
void swapBytes(void* number, int bytes_num)
{
unsigned __int8* ptr = number;
for (int i = 0; i<bytes_num/2; i++) {
unsigned __int8 tmp = ptr[i];
ptr[i] = ptr[bytes_num-1-i];
ptr[bytes_num-1-i] = tmp;
}
}
Then call it like this:
swapBytes(&big_number, sizeof(big_number));
Your solution is very over-engineered and also entirely unsuitable for embedded systems such as MPC57xx.
Any integer type can get safely iterated across using a pointer to character. Assuming uint8_t* is a character type for your compiler, it's as simple as this:
void little_to_big16 (uint8_t big [sizeof(uint16_t)],
const uint8_t little [sizeof(uint16_t)])
{
big[0] = little[1];
big[1] = little[0];
}
Then write big_to_little16, big_to_little32 etc etc as needed. Such functions can and should probably be inlined too.
Example of use:
#include <stdio.h>
#include <inttypes.h>
void little_to_big16 (uint8_t big [sizeof(uint16_t)],
const uint8_t little [sizeof(uint16_t)])
{
big[0] = little[1];
big[1] = little[0];
}
int main (void)
{
uint16_t little = 0xAABB;
uint16_t big;
little_to_big16((uint8_t*)&big, (uint8_t*)&little);
printf("%"PRIx16, big);
}
Output on x86 little endian:
bbaa

How do I cast a float pointer to a uint8_t pointer in Metal Shader Language?

I am trying to write the following C code in Metal Shading Language inside of a kernel void function:
float f = 2.1;
uint8_t byteArray[sizeof(f)];
for (int a = 0; a < sizeof(f); a++) {
byteArray[a] = ((uint8_t*)&f)[a];
}
The code is supposed to get a byte array of the float value. When I try to write the same code in Metal Shader Language, I get the following build-time error:
Pointer type must have explicit address space qualifier
I understand that Metal restricts the use of pointers and requires that arguments to a kernel function are provided with an explicit address space attribute such as device, constant, etc. How would I perform the type-cast in Metal Shading Language?
This isn't C++, so you have to do it the other way.
You can't use unions or reinterpret_cast in MSL properly.
Instead, there's a type for a vector of 4 uint8_ts, it's uchar4.
To do what you are trying to do, you would write it something like this.
float f = 2.1;
uchar4 ff = as_type<uchar4>(f);
Refer to the MSL spec, section 2.19 Type Conversions and Re-interpreting data.
As for address space qualifiers:
Every pointer in Metal Shading Language has an address qualifier. It can be a device, constant, thread, threadgroup and others. Refer to Chapter 4 in the spec.
These address qualifiers come from the fact that there are different memory spaces. You can read more about them in the document above.
Since f is local variable, it's in thread space, so your uint8_t pointer would have a type of thread uint8_t* and not just uint8_t.
So you could probably do it like this:
float f = 2.1;
thread uint8_t* ff = (thread uint8_t*)&f;
But I think the as_type approach is much more clear.
Don't know about metal specifically, but in ordinary C, you'd want to put f and byteArray inside a union
Here's some sample code:
#include <stdio.h>
#include <stdint.h>
union float_byte {
float f;
uint8_t byteArray[sizeof(float)];
};
union float_byte u;
void
dotest(float f)
{
u.f = f;
printf("%.6f",u.f);
for (int idx = 0; idx < sizeof(u.byteArray); ++idx)
printf(" %2.2X",u.byteArray[idx]);
printf("\n");
}
int
main(void)
{
dotest(2.1);
dotest(7.6328);
return 0;
}
Here's the program output:
2.100000 66 66 06 40
7.632800 E6 3F F4 40
UPDATE:
even today, isn't it still technically UB to read a union member that wasn't the last one written to? Although, it sounds like this is widely supported now with implementation-defined behavior. One of many related questions: stackoverflow.com/questions/2310483/… – yano
No, it's not UB for a number of reasons.
It might be "implementation defined" behavior, but only because of the CPU/processor endianness re. the format of a [32 bit] float in memory, if we wished to interpret the bytes in byteArray
But, AFAICT, that doesn't affect OP's issue since the point was just to get a byte buffer [for binary/serialization of the data?].
If one wanted to interpret the data (e.g. designing a DIY F.P. S/W implementation), then the format and endianness of the float would have to be known. This is [probably] IEEE 784 format, and the processor endianness.
But, using the union to just get a byte pointer, there is no issue. It's not even "implementation defined" behavior.
It's just about the same as:
float my_f = f;
uint8_t *byteArray = (uint8_t *) &my_f;
And, it works because it has to work.
Also, the union [as used here] is a common idiom, dating back to the 1970's so it has to be supported.
Also, it just works [because it has to by design].
If we had:
void
funcA(float f)
{
u.f = f;
}
void
funcB(void)
{
for (int idx = 0; idx < sizeof(u.byteArray); ++idx)
printf(" %2.2X",u.byteArray[idx]);
printf("\n");
}
For fun, assume funcA and funcB are in separate .c files. When funcA is called it changes the memory of u [in a predictable way].
Nothing in between changes the layout of u.
Then, we call funcB. The layout of the bytes in byteArray will be the same/predictable data.
This is similar to and works the same way as writing the float to a file as binary data:
#include <unistd.h>
int fd;
void
writefloat(float f)
{
float my_f = f;
write(fd,&my_f,sizeof(float));
}
void
writefloat2(float f)
{
write(fd,&f,sizeof(float));
}
void
writefloat3(float f)
{
write(fd,&f,sizeof(f));
}
Perhaps this would be easier to see if we used uint32_t instead of float. We could do an endian test. [Note: this is crude and doesn't account for oddball endianness like pdp11/vax]:
#include <stdio.h>
#include <stdint.h>
union uint_byte {
uint32_t i;
uint8_t b[sizeof(uint32_t)];
};
union uint_byte u;
int
main(void)
{
u.i = 0x01020304;
if (u.b[0] == 0x04)
printf("cpu is little-endian\n");
else
printf("cpu is big-endian\n");
return 0;
}
In c++ (20) you have bit_cast.
In the section 'Notes' you will see, that it is simply implemented as a call to memcpy.
So, in order to avoid 'undefined behaviour' and to be safe (besides of all the previous, it is also the fastest), just do:
memcpy(byteArray, &f, sizeof f); //size of byteArray must be at least: sizeof f

Dealing with data serialization without violating the strict aliasing rule

Often in embedded programming (but not limited to) there is a need to serialize some arbitrary struct in order to send it over some communication channel or write to some memory.
Example
Let's consider a structure composed of different data types in a N-aligned memory region:
struct
{
float a;
uint8_t b;
uint32_t c;
} s;
Now let's assume we have a library function
void write_to_eeprom(uint32_t *data, uint32_t len);
which is taking the pointer to data to be written as a uint32_t*. Now we would like to write s to the eeprom using this function. A naive approach would be to do something like
write_to_eeprom((uint32_t*)&s, sizeof(s)/4);
But it is a clear violation of the strict aliasing rule.
Second example
struct
{
uint32_t a;
uint8_t b;
uint32_t c;
} s;
In this case the aliasing (uint32_t*)&s is not violating the rule, as the pointer is compatible with the pointer to the first field type, which is legal. But! The library function can be implemented such that it is doing some pointer arithmetic to iterate the input data, while this arithmetic resulting pointers are incompatible with the data they are pointing to (for example data+1 is the pointer of type uint32_t*, but it might point to the uint8_t field). Which again a violation of the rule, as I understand it.
Possible solution?
Wrap the problematic structure in a union with array of the desired type:
union
{
struct_type s;
uint32_t array[sizeof(struct_type) / 4];
} u;
And pass the u.array to the library function.
Is this the right way to do this? Is this the only right way to do this? What could be some other approaches?
Just a note I am not entirely sure but it can be that it is not always safe to cast uint8_t* to char*(here).
Regardless, what does the last parameter of your write function want, number of bytes to write - or number of uint32_t elements? Let's assume later, and also assume you want to write each member of the struct to separate integer. You can do this:
uint32_t dest[4] = {0};
memcpy(buffer, &s.a, sizeof(float));
memcpy(buffer+1, &s.b, sizeof(uint8_t));
memcpy(buffer+2, &s.c, sizeof(uint32_t));
write_to_eeprom(buffer, 3 /* Nr of elements */);
If you want to copy the structure elements to the integer array consecutively - you can first copy the structure member to a byte array consecutively - and then copy the byte array to the uint32_t array. And also pass number of bytes as last parameter which would be - sizeof(float)+sizeof(uint8_t)+sizeof(uint32_t)
Consider that writing to eeprom is often slower, sometimes a lot slower, than writing to normal memory, that using an intervening buffer is rarely a performance drag. I realize this goes against this comment, yet I feel it deserves consideration as it handles all other C concerns
Write a helper function that has no alignment, aliasing nor size issues
extern void write_to_eeprom(/* I'd expect const */ uint32_t *data, uint32_t len);
// Adjust N per system needs
#define BYTES_TO_EEPROM_N 16
void write_bytes_to_eeprom(const void *ptr, size_t size) {
const unsigned char *byte_ptr = ptr;
union {
uint32_t data32[BYTES_TO_EEPROM_N / sizeof (uint32_t)];
unsigned char data8[BYTES_TO_EEPROM_N];
} u;
while (size >= BYTES_TO_EEPROM_N) {
memcpy(u.data8, byte_ptr, BYTES_TO_EEPROM_N); // **
byte_ptr += BYTES_TO_EEPROM_N;
write_to_eeprom(u.data32, BYTES_TO_EEPROM_N / sizeof (uint32_t));
size -= BYTES_TO_EEPROM_N;
}
if (size > 0) {
memcpy(u.data8, byte_ptr, size);
while (size % sizeof (uint32_t)) {
u.data8[size++] = 0; // zero fill
}
write_to_eeprom(u.data32, (uint32_t) size);
}
}
// usage - very simple
write_bytes_to_eeprom(&s, sizeof s);
** Could use memcpy(u.data32, byte_ptr, BYTES_TO_EEPROM_N); to handle #zwol issue.

C Function to Convert float to byte array

I'm trying to make a function that will accept a float variable and convert it into a byte array. I found a snippet of code that works, but would like to reuse it in a function if possible.
I'm also working with the Arduino environment, but I understand that it accepts most C language.
Currently works:
float_variable = 1.11;
byte bytes_array[4];
*((float *)bytes_array) = float_variable;
What can I change here to make this function work?
float float_test = 1.11;
byte bytes[4];
// Calling the function
float2Bytes(&bytes,float_test);
// Function
void float2Bytes(byte* bytes_temp[4],float float_variable){
*(float*)bytes_temp = float_variable;
}
I'm not so familiar with pointers and such, but I read that (float) is using casting or something?
Any help would be greatly appreciated!
Cheers
*EDIT: SOLVED
Here's my final function that works in Arduino for anyone who finds this. There are more efficient solutions in the answers below, however I think this is okay to understand.
Function: converts input float variable to byte array
void float2Bytes(float val,byte* bytes_array){
// Create union of shared memory space
union {
float float_variable;
byte temp_array[4];
} u;
// Overite bytes of union with float variable
u.float_variable = val;
// Assign bytes to input array
memcpy(bytes_array, u.temp_array, 4);
}
Calling the function
float float_example = 1.11;
byte bytes[4];
float2Bytes(float_example,&bytes[0]);
Thanks for everyone's help, I've learnt so much about pointers and referencing in the past 20 minutes, Cheers Stack Overflow!
Easiest is to make a union:
#include <stdio.h>
int main(void) {
int ii;
union {
float a;
unsigned char bytes[4];
} thing;
thing.a = 1.234;
for (ii=0; ii<4; ii++)
printf ("byte %d is %02x\n", ii, thing.bytes[ii]);
return 0;
}
Output:
byte 0 is b6
byte 1 is f3
byte 2 is 9d
byte 3 is 3f
Note - there is no guarantee about the byte order… it depends on your machine architecture.
To get your function to work, do this:
void float2Bytes(byte bytes_temp[4],float float_variable){
union {
float a;
unsigned char bytes[4];
} thing;
thing.a = float_variable;
memcpy(bytes_temp, thing.bytes, 4);
}
Or to really hack it:
void float2Bytes(byte bytes_temp[4],float float_variable){
memcpy(bytes_temp, (unsigned char*) (&float_variable), 4);
}
Note - in either case I make sure to copy the data to the location given as the input parameter. This is crucial, as local variables will not exist after you return (although you could declare them static, but let's not teach you bad habits. What if the function gets called again…)
Here's a way to do what you want that won't break if you're on a system with a different endianness from the one you're on now:
byte* floatToByteArray(float f) {
byte* ret = malloc(4 * sizeof(byte));
unsigned int asInt = *((int*)&f);
int i;
for (i = 0; i < 4; i++) {
ret[i] = (asInt >> 8 * i) & 0xFF;
}
return ret;
}
You can see it in action here: http://ideone.com/umY1bB
The issue with the above answers is that they rely on the underlying representation of floats: C makes no guarantee that the most significant byte will be "first" in memory. The standard allows the underlying system to implement floats however it feels like -- so if you test your code on a system with a particular kind of endianness (byte order for numeric types in memory), it will stop working depending on the kind of processor you're running it on.
That's a really nasty, hard-to-fix bug and you should avoid it if at all possible.
I would recommend trying a "union".
Look at this post:
http://forum.arduino.cc/index.php?topic=158911.0
typedef union I2C_Packet_t{
sensorData_t sensor;
byte I2CPacket[sizeof(sensorData_t)];
};
In your case, something like:
union {
float float_variable;
char bytes_array[4];
} my_union;
my_union.float_variable = 1.11;
Yet another way, without unions:
(Assuming byte = unsigned char)
void floatToByte(byte* bytes, float f){
int length = sizeof(float);
for(int i = 0; i < length; i++){
bytes[i] = ((byte*)&f)[i];
}
}
this seems to work also
#include <stddef.h>
#include <stdint.h>
#include <string.h>
float fval = 1.11;
size_t siz;
siz = sizeof(float);
uint8_t ures[siz];
memcpy (&ures, &fval, siz);
then
float utof;
memcpy (&utof, &ures, siz);
also for double
double dval = 1.11;
siz = sizeof(double);
uint8_t ures[siz];
memcpy (&ures, &dval, siz);
then
double utod;
memcpy (&utod, &ures, siz);
Although the other answers show how to accomplish this using a union, you can use this to implement the function you want like this:
byte[] float2Bytes(float val)
{
my_union *u = malloc(sizeof(my_union));
u->float_variable = val;
return u->bytes_array;
}
or
void float2Bytes(byte* bytes_array, float val)
{
my_union u;
u.float_variable = val;
memcpy(bytes_array, u.bytes_array, 4);
}
**conversion without memory reference** \
#define FLOAT_U32(x) ((const union {float f; uint32_t u;}) {.f = (x)}.u) // float->u32
#define U32_FLOAT(x) ((const union {float f; uint32_t u;}) {.u = (x)}.f) // u32->float
**usage example:**
float_t sensorVal = U32_FLOAT(eeprom_read_dword(&sensor));
First of all, some embedded systems 101:
Anyone telling you to use malloc/new on Arduino have no clue what they are talking about. I wrote a fairly detailed explanation regarding why here: Why should I not use dynamic memory allocation in embedded systems?
You should avoid float on 8 bit microcontrollers since it leads to incredibly inefficient code. They do not have a FPU, so the compiler will be forced to load a very resource-heavy software floating point library to make your code work. General advise here.
Regarding pointer conversions:
C allows all manner of wild and crazy pointer casts. However, there are lots of situations where it can lead to undefined behavior if you cast a character byte array's address into a float* and then de-reference it.
If the address of the byte array is not aligned, it will lead to undefined behavior on systems that require aligned access. (AVR doesn't care about alignment though.)
If the byte array does not contain a valid binary representation of a float number, it could become a trap representation. Similarly you must keep endianess in mind. AVR is an 8-bitter but it's regarded as little endian since it uses little endian format for 16 bit addresses.
It leads to undefined behavior because it goes against the C language "effective type" system, also known as a "strict pointer aliasing violation". What is the strict aliasing rule?
Going the other way around is fine though - taking the address of a float variable and converting it to a character pointer, then de-reference that character pointer to access individual bytes. Multiple special rules in C allows this for serialization purposes and hardware-related programming.
Viable solutions:
memcpy always works fine and then you won't have to care about alignment and strict aliasing. You still have to care about creating a valid floating point representation though.
union "type punning" as demonstrated in other answers. Note that such type punning will assume a certain endianess.
Bit shifting individual bytes and concatenating with | or masking with & as needed. The advantage of this is that it's endianess-independent in some scenarios.
float f=3.14;
char *c=(char *)&f;
float g=0;
char *d=(char *)&g;
for(int i=0;i<4;i++) d[i]=c[i];
/* Now g=3.14 */
Cast your float as char, and assign the address to the char pointer.
Now, c[0] through c[3] contain your float.
http://justinparrtech.com/JustinParr-Tech/c-access-other-data-types-as-byte-array/

Reading audio rlp

I am tring to get sound samples from microphone through Fez Panda 2. I am using rlp to accomplish that. Here is my code:
int GHAL_AnalogIn_Read(unsigned char channel)
{
return ((*((int*)(ADC_DATA_BASE_ADDRESS) + channel)) >>8) & 0x3FF;
}
int ReadAudio(unsigned int *generalArray, void **args, unsigned int argsCount ,unsigned int *argSize)
{
unsigned char *buffer = (unsigned char*)args[0];
int buffer_lengh = argSize[0];
unsigned char channel = *(unsigned char*)args[1];
int i=0;
while(i<buffer_lengh)
{
buffer[i] = GHAL_AnalogIn_Read(channel);
i++;
RLPext->Delay(100);
}
return 0;
}
The problem is that I need float values not unsigned char because I'm performing fft on these sound samples. So I need modification that will provide me float values. Any ideas?
Have you got experience with C? Especially with the meaning of * and &? * means: get the value pointed by address. So void ** args says someting like 'get the value pointed by the value obtained from address'. void is used to freely input anything you like. As you can not put whole structures or objects in an argument, you provide the pointer (an address) to a structure or object. By using the * you obtain the value on the address of the argument.
In C you do not pass whole arrays in an argument, you pass on the address of the first index.
Now you could simply re-factor your function to be something like:
int ReadAudio(unsigned int *generalArray, float arg, unsigned int argsCount ,unsigned int *argSize)
But as void **args is pointing to a buffer now, I think you should know what operation you want to perform on the data collected. An analog read will always provide you with an integer, most ADC (analog - digital - converter) are 10-bit or so.
If a float is 4 bytes on a 32-bit system, you want to mangle your data (unsigned char *buffer) in a 4-byte boundary.
EDIT: I have overlooked this in the documentatio: Note: Parameter of all function in RLP code file must have format follow this:Note: Parameter of all function in RLP code file must have format follow this:. Just cast the buffer bytes to a float by 4 byte boundary and I think you will do fine.

Resources