Ich versuche, eine Funktion zu erstellen, die eine Float-Variable akzeptiert und in ein Byte-Array konvertiert. Ich habe ein Codefragment gefunden, das funktioniert, aber ich möchte es gerne in einer Funktion wiederverwenden.
Ich arbeite auch mit der Arduino-Umgebung, aber ich verstehe, dass die meisten C-Sprachen akzeptiert werden.
Derzeit arbeitet:
float_variable = 1.11;
byte bytes_array[4];
*((float *)bytes_array) = float_variable;
Was kann ich hier ändern, damit diese Funktion funktioniert?
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;
}
Ich bin nicht so vertraut mit Zeigern und so, aber ich habe gelesen, dass (Float ) Casting oder etwas verwendet?
Jede Hilfe wäre sehr dankbar!
Prost
* EDIT: Gelöst
Hier ist meine letzte Funktion, die in Arduino für jeden funktioniert, der dies findet. In den Antworten finden Sie effizientere Lösungen, aber ich denke, das ist in Ordnung zu verstehen.
Funktion: Konvertiert die Float-Eingangsvariable in ein 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);
}
Funktion aufrufen
float float_example = 1.11;
byte bytes[4];
float2Bytes(float_example,&bytes[0]);
Vielen Dank für die Hilfe aller, ich habe in den letzten 20 Minuten so viel über Zeiger und Referenzierung gelernt, Cheers Stack Overflow!
Am einfachsten ist es, eine Gewerkschaft zu bilden:
#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;
}
Ausgabe:
byte 0 is b6
byte 1 is f3
byte 2 is 9d
byte 3 is 3f
Hinweis - Es gibt keine Garantie für die Reihenfolge der Bytes… diese hängt von Ihrer Rechnerarchitektur ab.
Um Ihre Funktion zum Laufen zu bringen, machen Sie folgendes:
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);
}
Oder um es wirklich zu hacken:
void float2Bytes(byte* bytes_temp[4],float float_variable){
memcpy(bytes_temp, (unsigned char*) (&float_variable), 4);
}
Hinweis - In jedem Fall muss die Daten an den als Eingabeparameter angegebenen Ort kopiert werden. Dies ist von entscheidender Bedeutung, da lokale Variablen nach Ihrer Rückkehr nicht vorhanden sind (obwohl Sie sie als static
deklarieren könnten, aber lehnen wir Sie nicht schlechte Gewohnheiten an.
Hier ist eine Möglichkeit, das zu tun, was Sie möchten, das nicht kaputt geht, wenn Sie sich in einem System mit einer anderen endianness von dem System befinden, das Sie gerade verwenden:
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;
}
Sie können es hier in Aktion sehen: http://ideone.com/umY1bB
Das Problem bei den obigen Antworten ist, dass sie sich auf die zugrunde liegende Darstellung von float
s verlassen: C garantiert nicht, dass das höchstwertige Byte im Speicher "das erste" ist. Der Standard erlaubt es dem zugrundeliegenden System, float
s zu implementieren, jedoch fühlt es sich so an - wenn Sie also Ihren Code auf einem System mit einer bestimmten Art von Endianness (Byte-Reihenfolge für numerische Typen im Speicher) testen, funktioniert je nach Art nicht mehr des Prozessors laufen Sie auf.
Das ist ein wirklich böser, schwer zu reparierender Fehler, den Sie möglichst vermeiden sollten.
Ich würde empfehlen, eine "Gewerkschaft" zu versuchen.
Schau dir diesen Beitrag an:
http://forum.arduino.cc/index.php?topic=158911.0
typedef union I2C_Packet_t{
sensorData_t sensor;
byte I2CPacket[sizeof(sensorData_t)];
};
In Ihrem Fall so etwas wie:
union {
float float_variable;
char bytes_array[4];
} my_union;
my_union.float_variable = 1.11;
Noch ein anderer Weg ohne Gewerkschaften: (Angenommen, Byte = unsigniertes Zeichen)
void floatToByte(byte* bytes, float f){
int length = sizeof(float);
for(int i = 0; i < length; i++){
bytes[i] = ((byte*)&f)[i];
}
}
Obwohl die anderen Antworten zeigen, wie dies mit einer Union erreicht werden kann, können Sie die gewünschte Funktion folgendermaßen implementieren:
byte[] float2Bytes(float val)
{
my_union *u = malloc(sizeof(my_union));
u->float_variable = val;
return u->bytes_array;
}
oder
void float2Bytes(byte* bytes_array, float val)
{
my_union u;
u.float_variable = val;
memcpy(bytes_array, u.bytes_array, 4);
}
das scheint auch zu funktionieren
#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);
dann
float utof;
memcpy (&utof, &ures, siz);
auch für doppeltes
double dval = 1.11;
siz = sizeof(double);
uint8_t ures[siz];
memcpy (&ures, &dval, siz);
dann
double utod;
memcpy (&utod, &ures, siz);