c casting floating-point arduino bytearray

Función C para convertir float a byte array



casting floating-point (6)

Estoy tratando de hacer una función que acepte una variable flotante y la convierta en una matriz de bytes. Encontré un fragmento de código que funciona, pero me gustaría reutilizarlo en una función si es posible.

También estoy trabajando con el entorno Arduino, pero entiendo que acepta la mayoría del lenguaje C.

Actualmente funciona:

float_variable = 1.11; byte bytes_array[4]; *((float *)bytes_array) = float_variable;

¿Qué puedo cambiar aquí para que esta función funcione?

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

No estoy tan familiarizado con los punteros y demás, pero ¿leí que (flotar ) está usando casting o algo así?

Cualquier ayuda sería muy apreciada!

Aclamaciones

* EDITAR: SOLUCIONADO

Aquí está mi función final que funciona en Arduino para cualquiera que encuentre esto. Hay soluciones más eficientes en las respuestas a continuación, sin embargo, creo que esto está bien de entender.

Función: convierte la variable flotante de entrada en una matriz de bytes

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

Llamando a la función

float float_example = 1.11; byte bytes[4]; float2Bytes(float_example,&bytes[0]);

Gracias por la ayuda de todos, he aprendido mucho sobre punteros y referencias en los últimos 20 minutos, ¡Cheers Stack Overflow!


Aunque las otras respuestas muestran cómo lograr esto usando una unión, puede usar esto para implementar la función que desea de esta manera:

byte[] float2Bytes(float val) { my_union *u = malloc(sizeof(my_union)); u->float_variable = val; return u->bytes_array; }

o

void float2Bytes(byte* bytes_array, float val) { my_union u; u.float_variable = val; memcpy(bytes_array, u.bytes_array, 4); }


Esta es una manera de hacer lo que quiere que no se romperá si está en un sistema con una endianness diferente de la que está ahora:

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

Puedes verlo en acción aquí: http://ideone.com/umY1bB

El problema con las respuestas anteriores es que se basan en la representación subyacente de float s: C no garantiza que el byte más significativo será "primero" en la memoria. Sin embargo, el estándar permite que el sistema subyacente implemente float s, así que si prueba su código en un sistema con un tipo particular de endianidad (orden de bytes para los tipos numéricos en la memoria), dejará de funcionar dependiendo del tipo de procesador en el que lo está ejecutando .

Es un error realmente desagradable y difícil de solucionar, y debes evitarlo si es posible.


Lo más fácil es hacer una unión:

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

Salida:

byte 0 is b6 byte 1 is f3 byte 2 is 9d byte 3 is 3f

Nota: no hay garantía sobre el orden de bytes ... depende de la arquitectura de su máquina.

Para que tu función funcione, haz esto:

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

O para realmente hackearlo:

void float2Bytes(byte* bytes_temp[4],float float_variable){ memcpy(bytes_temp, (unsigned char*) (&float_variable), 4); }

Nota: en cualquier caso, me aseguro de copiar los datos en la ubicación indicada como parámetro de entrada. Esto es crucial, ya que las variables locales no existirán después de que regrese (aunque podría declararlas static , pero no le enseñemos malos hábitos. ¿Qué sucede si se vuelve a llamar a la función ...)


Otra forma más, sin uniones: (asumiendo 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]; } }


Recomendaría intentar una "unión".

Mira este post:

http://forum.arduino.cc/index.php?topic=158911.0

typedef union I2C_Packet_t{ sensorData_t sensor; byte I2CPacket[sizeof(sensorData_t)]; };

En tu caso, algo como:

union { float float_variable; char bytes_array[4]; } my_union; my_union.float_variable = 1.11;


esto parece funcionar tambien

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

entonces

float utof; memcpy (&utof, &ures, siz);

también para doble

double dval = 1.11; siz = sizeof(double); uint8_t ures[siz]; memcpy (&ures, &dval, siz);

entonces

double utod; memcpy (&utod, &ures, siz);