J'essaie de créer une fonction qui acceptera une variable float et la convertira en tableau d'octets. J'ai trouvé un extrait de code qui fonctionne, mais j'aimerais le réutiliser dans une fonction si possible.
Je travaille également avec l'environnement Arduino, mais je comprends qu'il accepte la plupart des langages C.
Travaille actuellement:
float_variable = 1.11;
byte bytes_array[4];
*((float *)bytes_array) = float_variable;
Que puis-je changer ici pour que cette fonction fonctionne?
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;
}
Je ne connais pas très bien les pointeurs, mais j'ai lu que (float ) utilise un casting ou quelque chose?
Toute aide serait grandement appréciée!
À votre santé
* EDIT: RESOLU
Voici ma fonction finale qui fonctionne dans Arduino pour quiconque trouve cela. Les réponses ci-dessous contiennent des solutions plus efficaces, mais je pense que cela peut être compris.
Fonction: convertit la variable float en entrée en tableau d'octets
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);
}
Appeler la fonction
float float_example = 1.11;
byte bytes[4];
float2Bytes(float_example,&bytes[0]);
Merci à tous pour votre aide. Au cours des 20 dernières minutes, j'ai beaucoup appris sur les pointeurs et les références, Cheers Stack Overflow!
Le plus simple est de faire une 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;
}
Sortie:
byte 0 is b6
byte 1 is f3
byte 2 is 9d
byte 3 is 3f
Remarque - l'ordre des octets n'est pas garanti… cela dépend de l'architecture de votre machine.
Pour que votre fonction fonctionne, procédez comme suit:
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);
}
Ou pour vraiment le pirater:
void float2Bytes(byte* bytes_temp[4],float float_variable){
memcpy(bytes_temp, (unsigned char*) (&float_variable), 4);
}
Remarque - dans les deux cas, je m'assure de copier les données à l'emplacement indiqué comme paramètre d'entrée. Ceci est crucial, car les variables locales n'existeront plus après votre retour (bien que vous puissiez les déclarer static
, mais ne vous enseignons pas les mauvaises habitudes. Et si la fonction était appelée à nouveau…)
Voici une façon de faire ce que vous voulez, qui ne casse pas si vous êtes sur un système avec un endianness différent de celui sur lequel vous vous trouvez:
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;
}
Vous pouvez le voir en action ici: http://ideone.com/umY1bB
Le problème avec les réponses ci-dessus est qu'elles s'appuient sur la représentation sous-jacente de float
s: C ne garantit pas que l'octet le plus significatif sera "le premier" en mémoire. La norme permet au système sous-jacent d'implémenter float
s comme vous le souhaitez - donc si vous testez votre code sur un système avec un type particulier d'endianness (ordre d'octet pour les types numériques en mémoire), il ne fonctionnera plus en fonction du type du processeur que vous exécutez sur.
C'est un bug vraiment méchant, difficile à résoudre et que vous devriez éviter si possible.
Je recommanderais d'essayer une "union".
Regardez ce post:
http://forum.arduino.cc/index.php?topic=158911.0
typedef union I2C_Packet_t{
sensorData_t sensor;
byte I2CPacket[sizeof(sensorData_t)];
};
Dans votre cas, quelque chose comme:
union {
float float_variable;
char bytes_array[4];
} my_union;
my_union.float_variable = 1.11;
Encore une autre manière, sans union: (En supposant que byte = caractère non signé)
void floatToByte(byte* bytes, float f){
int length = sizeof(float);
for(int i = 0; i < length; i++){
bytes[i] = ((byte*)&f)[i];
}
}
Bien que les autres réponses montrent comment accomplir cela en utilisant une union, vous pouvez l'utiliser pour implémenter la fonction de votre choix:
byte[] float2Bytes(float val)
{
my_union *u = malloc(sizeof(my_union));
u->float_variable = val;
return u->bytes_array;
}
ou
void float2Bytes(byte* bytes_array, float val)
{
my_union u;
u.float_variable = val;
memcpy(bytes_array, u.bytes_array, 4);
}
cela semble fonctionner aussi
#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);
puis
float utof;
memcpy (&utof, &ures, siz);
aussi pour double
double dval = 1.11;
siz = sizeof(double);
uint8_t ures[siz];
memcpy (&ures, &dval, siz);
puis
double utod;
memcpy (&utod, &ures, siz);