float in vier ints zerlegen



  • Hallo,

    ich möchte eine 32-Bit Fließkommazahl zur Übertragung über eine UDP Verbindung in einen char* umwandeln. da dies mit _fcvt nicht verlustfrei möglich ist, habe ich versucht, die 32-Bit in je 8-Bit zuu zerlegen, was wiederum einem int bzw. char entspricht, die char Repräsentationen zu übertragen und dann wieder zusammenzusetzen. Zum Test habe ich mir ein kleines Programm geschreiben, was eine float Zahl zerlegen und wiederzusammensetzen soll, leider funktioniert es nicht, das Ergebis unterscheidet sich von der Urspungszahl 😞

    Wo ist mein Denkfehler? 😕

    Danke & Gruß

    Tobias

    #include <stdio.h>
    #include <stdlib.h>
    #include <memory.h>
    
    int main() {
        float* myFloat = (float*)calloc(1,sizeof(float));
    	*myFloat = (float)3.141;
    	printf("myFloat = %.6f\n", *myFloat);
    
    	int* buffer1 = (int*)calloc(1,sizeof(int));
    	memcpy(buffer1,myFloat,1);
    	printf("buffer1 = %d ", *buffer1);
    
    	int* buffer2 = (int*)calloc(1,sizeof(int));
    	memcpy(buffer2,myFloat+1,1);
    	printf("buffer2 = %d ", *buffer2);
    
    	int* buffer3 = (int*)calloc(1,sizeof(int));
    	memcpy(buffer3,myFloat+2,1);
    	printf("buffer3 = %d ", *buffer3);
    
    	int* buffer4 = (int*)calloc(1,sizeof(int));
    	memcpy(buffer4,myFloat+3,1);
    	printf("buffer4 = %d ", *buffer4);
    
    	printf("\n");
    
    	float* newFloat = (float*)calloc(1,sizeof(float));
    	memcpy(newFloat,buffer1,1);
    	memcpy(newFloat+1,buffer2,1);
    	memcpy(newFloat+2,buffer3,1);
    	memcpy(newFloat+3,buffer4,1);
    	printf("newFloat = %.6f\n", *newFloat);
    }
    


  • Warum castest du dein float nicht einfach?

    char* pTest = (char*)myFloat;
    


  • *patsch* Oh man, warum einfach, wenn's auch kompliziert geht? 🤡
    Das kommt vom nächtelangen programmieren.

    Danke für die Hilfe 🙂



  • char* pTest = (char*)myFloat;
    

    Das wird nicht gehen! Versuch lieber das:

    char* pTest = (char*)&myFloat;
    


  • jemand schrieb:

    char* pTest = (char*)myFloat;
    

    Das wird nicht gehen! Versuch lieber das:

    char* pTest = (char*)&myFloat;
    

    Es funktioniert aber nur die erste Lösung 😕



  • Es funktioniert aber nur die erste Lösung

    ?
    In der ersten Lösung werden die 32 bit des Floats genommen und in ein 32 bit Pointer geschrieben. Dieser Pointer zeigt dann aber nicht auf den Float sonder auf irgend eine Stelle in der Memory. Also kann (sollte) das nicht klappen. Um die Addresse eines Float zu bekommen muss man ein & setzten.

    Nur um sicher zu gehen du benutzt den char* ja als Array:

    char* pTest = (char*)&myFloat;
    pTest[0]=byte1;
    pTest[1]=byte2;
    pTest[2]=byte3;
    pTest[3]=byte4;
    

    Also

    char* pTest = (char*)myFloat;
    

    Will mein Compiler noch nicht mal schlucken. Und selbst wenn er es schlucken würde müsste das ein Acess violation verursachen.



  • Nur so am Rande, genau für solche Zwecke sind doch die unions gedacht oder?



  • sirlant
    *******

    nö, nich für direkte typumwandlung, das ist nur ein "nützlicher" nebeneffekt, aber natürlich kann man es auch mit unions lösen 🙂

    MrBigglesworth
    **************

    int main(void)
    {
    
    	char *test = malloc(4*sizeof(*test));
    	float *blubb;
    	float blah = 32000.45;
    
    	blubb=&blah;
    
    	memcpy(test,blubb,sizeof(*blubb));
    
    	printf("%d ",test[0]);
    	printf("%d ",test[1]);
    	printf("%d ",test[2]);
    	printf("%d ",test[3]);
    
    return 0;
    }
    

    oder halt mit ner union

    bye

    tt



  • Sorry ich seh jetzt wo das problem ist. Ich dein Code nur überflogen und bin davon ausgegangen, dass myFloat ein float und nicht ein float* ist. Fals myFloat ein bereits ein pointer ist muss man das & natürlich weglassen.



  • jemand schrieb:

    char* pTest = (char*)myFloat;
    

    Das wird nicht gehen! Versuch lieber das:

    char* pTest = (char*)&myFloat;
    

    Tolle Idee 🙄 ! myFloat ist ein float* und kein float!



  • Du weißt, dass die Darstellung von Gleitkommazahlen nicht portabel zwischen verschiedenen Architekturen ist? Wird deine Zahl im little endian oder big endian format gespeichert? Mach doch einfach ein sprintf und gebe eine bestimmte Genauigkeit an.

    Gruß Tobias



  • Wie wärs damit?

    typedef union
    {
        float floatvalue;
        char bytes[4];
    }float_frickel_teil;
    

    Dann kannst Du den float-Wert in floatval packen und dann die Bytes aus bytes[0..3] auslesen und umgekehrt wobei man natürlich mit dem Alignment aufpassen muss.



  • tobidope schrieb:

    Du weißt, dass die Darstellung von Gleitkommazahlen nicht portabel zwischen verschiedenen Architekturen ist? Wird deine Zahl im little endian oder big endian format gespeichert? Mach doch einfach ein sprintf und gebe eine bestimmte Genauigkeit an.

    Gruß Tobias

    Ja, die Systeme sind aber identisch, da sist der Vorteil. Da ich Koordinaten ais openGL übertrage, ist eien bestimmte Genauigkeit nicht zulässig bzw. müssen die Zahlen exakt übertragen werden, da sonst z.B. unschöne Löcher in Modellen entstehen, die auf Rundungen zurückzuführen sind. Sonst könnt ich ja auch alles in einen int casten! 😉

    Gruß (auch) Tobias 😃


Log in to reply