C Function to Convert float to byte array

2019-01-22 00:07发布

问题:

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!

回答1:

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…)



回答2:

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.



回答3:

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;


回答4:

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];
  }

}


回答5:

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);
}


回答6:

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);