web-dev-qa-db-de.com

C Funktion zur Umwandlung von Float in Byte-Array

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!

16
Ben Winding

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.

21
Floris

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 floats verlassen: C garantiert nicht, dass das höchstwertige Byte im Speicher "das erste" ist. Der Standard erlaubt es dem zugrundeliegenden System, floats 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. 

7
Patrick Collins

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;
5
FoggyDay

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

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);
1
Enzo Guerra