Probleme mit reinterpret_cast<double*>



  • CStoll schrieb:

    Vergleich doch einmal sizeof(int) und sizeof(double) - gut möglich, daß du den hinteren Teil des double's verschluckt (und auf dem Rückweg mit Datenmüll gefüllt) hast.

    (aber daß immer der selbe Wert rauskommt, ist auch seltsam)

    Ja das sind 4 und 8. Daran könnte es natürlich liegen, daß nicht exakt die Werte rauskommen, aber immer derselbe Wert?



  • Wenn ich bei der Konvertierung folgendes mache:

    unsigned int *o;
    double original;
    o = reinterpret_cast<unsigned int*>(&original);
    

    Ist dann das double in o[0] und o[1] gespeichert?



  • Vermutlich ja.



  • Hallo,

    für deinen Zeiger auf double steht nicht genug 'korrekten' Speicherplatz
    zur Verfügung.
    Nach dem Cast zeigt er auf die 4 Byte von unsigned int und auf weitere 4
    undefinierte Byte im Arbeitsspeicher.

    Das bei dir immer der selbe Wert rauskommt, mag daran liegen, das die undefinierten 4 Byte den Exponenten auf einen ebenfalls undefinierten Wert setzen.
    Von den 11 Bit für den Exponenten sind nämlich 2 Bit für NaN- und INF-Fälle vorgesehen, wenn diese gesetzt sind, kommt halt Ramsch raus.

    Wenn du vorher Speicher reservierst, indem du z.B. eine double variable
    deklarierst und dann die Bits der unsigned int variable dort
    reinkopierst, dann klappt das.
    Es kommen Ergebnisse raus, die sich im Wertebereich von double bewegen.

    In c++ kenne ich keine Funktion, die man statt memcpy nehmen könnte:

    int main()
    {
    	double k = 0.0;
    	unsigned int komp = 3258761612;
    
     	memcpy( &k, &komp, sizeof(unsigned int) );
    	cout << k << endl;
    
    	komp = 123176233;
    	k = 0.0;
    	memcpy( &k, &komp, sizeof(unsigned int) );
    	cout << k << endl;
    
    	komp = 1538900071;
    	k = 0.0;
    	memcpy( &k, &komp, sizeof(unsigned int) );
    	cout << k << endl;
    
    	return 0;
    }
    

    🙂



  • proggingmania schrieb:

    In c++ kenne ich keine funktion, die man statt memcpy nehmen könnte:

    std::copy( )

    ...



  • kenner der dummköpfe schrieb:

    proggingmania schrieb:

    In c++ kenne ich keine funktion, die man statt memcpy nehmen könnte:

    std::copy( )

    ...

    Ja, sehr nett, aber für die Anwendung unbrauchbar 😉
    (um auf Byte-Ebene hantieren zu können, sind die passenden C-Funktionen doch ideal)

    @pm: Die Alternative wäre höchstens noch, einen int und double in einer union zu verstauen 😉



  • kenner der dummköpfe schrieb:

    proggingmania schrieb:

    In c++ kenne ich keine funktion, die man statt memcpy nehmen könnte:

    std::copy( )
    ...

    Klasse anonymer Mr. Schlaukopf und wie soll das in Form von Quelltext aussehen ?
    Ich bekomme da:

    error C2782: '_OI __cdecl std::copy(_II,_II,_OI)' : Vorlagenparameter '_II' ist mehrdeutig
    


  • proggingmania schrieb:

    int main()
    {
    	double k = 0.0;
    	unsigned int komp = 3258761612;
    
     	memcpy( &k, &komp, sizeof(unsigned int) );
    	cout << k << endl;
    
    	komp = 123176233;
    	k = 0.0;
    	memcpy( &k, &komp, sizeof(unsigned int) );
    	cout << k << endl;
    
    	komp = 1538900071;
    	k = 0.0;
    	memcpy( &k, &komp, sizeof(unsigned int) );
    	cout << k << endl;
    
    	return 0;
    }
    

    🙂

    Danke dafür. Nur noch eine Frage. Wenn ich nun den Hinweg anschaue, muss ich anscheinend mein double in 2 unsigned int speichern, richtig?
    Wie kann ich diese beiden dann wieder zusammenführen?

    Also konkret würde ich jetzt so vorgehen:

    double k = 1.2345;  
    unsigned int komp*;
    
    memcpy( &komp, &k, sizeof(double) );
    

    So daß ich den double-Wert in komp[0] und komp[1] gespeichert habe.
    oder wenn das nicht klappt:

    double k = 1.2345;  
    unsigned int komp*;
    komp = reinterpret_cast<unsigned int*>(&k);
    

    Nur wie bekomme ich den Rückweg hin? Ich müßte ja jetzt komp[0] und komp[1] zurückführen nach k.

    Florian



  • Wenn du die beiden int-Werte die ganze Zeit am Stück hältst, sollte der Rückweg eigentlich genauso klappen wie der Hinweg:

    double dval;
    unsigned int ival[sizeof(double)/sizeof(int)];
    
    dval=170.0;
    memcpy(ival,&dval,sizeof(double));
    ...
    memcpy(&dval,ival,sizeof(double));
    cout<<dval;
    


  • CStoll schrieb:

    Wenn du die beiden int-Werte die ganze Zeit am Stück hältst, sollte der Rückweg eigentlich genauso klappen wie der Hinweg:

    double dval;
    unsigned int ival[sizeof(double)/sizeof(int)];
    
    dval=170.0;
    memcpy(ival,&dval,sizeof(double));
    ...
    memcpy(&dval,ival,sizeof(double));
    cout<<dval;
    

    Danke. Ich werde es mal versuchen einzubauen.

    Florian



  • floriank schrieb:

    double k = 1.2345;  
    unsigned int komp*;
    
    memcpy( &komp, &k, sizeof(double) );
    

    pass auf mit sowas. du kopierst den inhalt von k hier in nicht allozierten speicher. vergleich das mit cstolls beispiel von eben.



  • thordk schrieb:

    pass auf mit sowas. du kopierst den inhalt von k hier in nicht allozierten speicher. vergleich das mit cstolls beispiel von eben.

    Viel schlimmer, er multipliziert eine Variablendefinition mit dem Ende der Zeile 😉

    *scnr*



  • naja, und eigentlich versucht er auch den inhalt von k dahin zu schreiben, wo die adresse von komp steht (wenn man mal annimmt, dass die zeile richtig wär). aber das sind spitzfindigkeiten 😃



  • thordk schrieb:

    floriank schrieb:

    double k = 1.2345;  
    unsigned int komp*;
    
    memcpy( &komp, &k, sizeof(double) );
    

    pass auf mit sowas. du kopierst den inhalt von k hier in nicht allozierten speicher. vergleich das mit cstolls beispiel von eben.

    den Speicher habe ich schon alloziert:

    komp = (unsigned int*) calloc(sizeof (unsigned int), 2);
    


  • yikes, warum schreibst nich einfach unsigned komp[2]; ?



  • Hallo,

    das richtige bekomme ich immer noch nicht zurück. Ich mache folgendes:

    double data_double;
    unsigned int* original;
    original = (unsigned int*) calloc(sizeof (unsigned int), 2);
    original = konvertierung_double (data_double);
    
    unsigned int* konvertierung_double(double original)
    {
        unsigned int* o;
        o = (unsigned int*) calloc(sizeof (unsigned int), 2);
    
        // Fall original ist positiv (inkl. +0)
    
        if (original >= 0 )
        {
    	original *= (-1) ;
            // float wird als unsigned int interpretiert
    	memcpy(o,&original,sizeof(double));
        }
    
        // Fall original ist negativ (inkl. -0)
    
        else
        {
            // Konvertierung in ein unsigned int
    	memcpy(o,&original,sizeof(double));
            // alle Bits werden einzeln negiert
            o[0]=~o[0];
        }
        // Rückgabe des Wertes nach der Konvertierung
        return(o);
    }
    double unkomp_double;
    unkomp_double= konvertierunginverse_double(original);
    
    double konvertierunginverse_double(unsigned int* komp)
    {
    
    	double* k;
    	k = (double*) calloc(sizeof (unsigned int), 1);
    
    	// Fall original ist positiv (inkl. +0)
    
    	unsigned int positiv = potenzieren(2,31);
    	if (komp[0] >= positiv )
    	{
    		// float wird als unsigned int interpretiert
    		komp[0] = komp[0] - positiv;
    		memcpy(k,komp,sizeof(double));
    	}
    
    	// Fall original ist negativ (inkl. -0)
    
    	else
    	{
    		komp[0] = ~komp[0];
    		// Konvertierung in ein unsigned int
    		memcpy(k,komp,sizeof(double));
    
    	}
    	// Rückgabe des Wertes nach der Konvertierung
    	return(k[0]);
    }
    

    Normalerweise sollte nun unkomp_double=data_double

    Ist es aber nicht. Mache ich noch etwas falsch?



  • Erstmal hast du da ein Memory-Leck in der Funktion (bzw. der vor dem Funktionseintritt angeforderte Speicher verschwindet im Nirvana).

    Und zweitens: Bist du sicher, daß die Bit-Anpassungen in den Funktionen auch zueinander passen? (vereinfache mal den Test, indem du die Fallunterscheidungen 'if(original>=0)...' bzw. 'if(komp[0]>=positiv)' weglässt)



  • CStoll schrieb:

    Und zweitens: Bist du sicher, daß die Bit-Anpassungen in den Funktionen auch zueinander passen? (vereinfache mal den Test, indem du die Fallunterscheidungen 'if(original>=0)...' bzw. 'if(komp[0]>=positiv)' weglässt)

    ja da bin ich mir eigentlich sicher. Zumindest stimmen diese, wenn es sich um floats handelt und somit der zweite Teil (also komp[1] usw. wegfällt).

    Warum verschwindet der Speicherplatz? Wird der in der Funktion nicht mit übernommen, wenn doch der Zeiger mit übergeben wird?

    Vielleicht verwirren die Bezeichnungen etwas. Ich habe das aus einem großen Programm herauskopiert. Ich bin mir eben nur sicher, daß es dazwischen alles funktioniert.



  • floriank schrieb:

    ja da bin ich mir eigentlich sicher. Zumindest stimmen diese, wenn es sich um floats handelt und somit der zweite Teil (also komp[1] usw. wegfällt).

    Wenn der Zeiger übergeben wird, ja. Aber du übergibst ja nicht den Zeiger, der im Hauptprogramm mit Speicher versorgt wurde, sondern legst in der Funktion neuen Speicher an, der zurückgegeben wird.

    Edit: Und daß die Umwandlungen mit floats klappen, beweist noch lange nichts über double's 😉



  • Müßtes denn dann eigentlich nicht klappen, wenn ich aus den Zeigern arrays[2] mache?

    Nur das funktioniert auch nicht.

    Also anstatt:

    unsigned int* original;
    original = (unsigned int*) calloc(sizeof (unsigned int), 2);
    
    unsigned int original[2];
    

    usw.


Anmelden zum Antworten