Probleme mit reinterpret_cast<double*>



  • 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.



  • floriank schrieb:

    Normalerweise sollte nun unkomp_double=data_double
    Ist es aber nicht. Mache ich noch etwas falsch?

    Ja. 😃

    k = (double*) calloc(sizeof (unsigned int), 1);
    

    Etwas zu wenig für double 😉

    komp[0] = ~komp[0];
    

    Ich nehme an, das du damit gleichzeitig das MSB invertieren möchtest( wegen der Abfrage in Zeile 48 ), das liegt aber an Position komp[1]

    if (komp[0] >= positiv );
    

    siehe 2)
    Also, setze Index 1 statt 0

    🕶



  • CStoll schrieb:

    (um auf Byte-Ebene hantieren zu können, sind die passenden C-Funktionen doch ideal)

    'std::uninitialized_copy'.

    *scnr*



  • ich mag memcpy. bilde mir ein, dass es schneller ist als alles andere 😃



  • Konrad Rudolph schrieb:

    CStoll schrieb:

    (um auf Byte-Ebene hantieren zu können, sind die passenden C-Funktionen doch ideal)

    'std::uninitialized_copy'.
    *scnr*

    Das war wohl jetzt ein "insider" 🙄
    Als ob man in C nicht variablen initialisieren könnte 🙄
    Klar, nehmen wir copy, brauchen wir nur noch eine Klasse für int und eine für double zu schreiben 🙄
    🙄



  • ************* schrieb:

    Klar, nehmen wir copy, brauchen wir nur noch eine Klasse für int und eine für double zu schreiben 🙄

    aja...

    Muss man das jetzt verstehen?

    #include <algorithm>
    #include <iostream>
    
    using namespace std;
    
    int main( ) {
    
    	int number = 0xff;
    	int target = 14;
    
    	cout << "number: " << number << "\ntarget: " << target << endl;
    
    	std::copy< int*, int* >( &number, &( &number )[ 1 ], &target );
    
    	cout << "\nnumber: " << number << "\ntarget: " << target << endl;
    }
    

    greetz, Swordfish



  • thordk schrieb:

    ich mag memcpy. bilde mir ein, dass es schneller ist als alles andere 😃

    Es ist aber – zumindest in der Theorie – umgekehrt. 'std::copy' kann nämlich durch tag resolution und andere Techniken (partielle Template-Spezialisierung) für unterschiedliche Typen entsprechende Optimierungen durchführen (Boost hat dazu nen Beispiel für Boost.TypeTraits), sodass für jeden Typ die optimale Routine gewählt wird (z.B. 'memcpy', falls das am effizientesten sein sollte. 'memcpy' kann das nicht. Natürlich kann das dadurch ausgeglichen werden, dass der Compiler "schummelt" indem er Analysen durchführt aber, um Stroustrup frei zu zitieren, es ist immer besser, wenn man etwas über Bibliotheken lösen kann, als es über die Sprache (sprich, den Compiler) zu lösen.



  • Was ist mit deinem Konverter, läuft das jetzt ?



  • Hallo,

    sorry, daß ich mich erst verspätet wieder melde, aber mein Internet war tot.

    Vielen Dank für die Hilfen. Es funktioniert nun alles wie gewünscht. Das memcpy funktioniert und ich habe nun auch die Reihenfolge richtig, in der in das int array geschrieben wird.

    Ich habe nur noch ein Problem mit der Genauigkeit der Rekonstruktion (Wenn ich ein 3-D Datenfeld einlese bzw. erzeuge und dieses zu groß wird, schleichen sich kleine Abweichungen im Nachkommabereich ein, bei 2-D ist das kein Problem). Dies wird aber nicht am Konverter oder so liegen, da es dort ja egal ist, wieviele und wie ich meine Daten gespeichert habe. Seltsam ist es trotzdem.

    Danke
    floriank



  • Was spricht eigentlich gegen eine Union?
    Ich hatte es jedenfalls so verstanden, als dass eine Menge an double-Werten vorliegt, diese dann, als int-Werte interpretiert, behandelt wird und soll anschließend wieder als double-Werte interpretiert werden.

    Man könnte doch

    union
    {
        double d;
        unsigned __int32 i[2];
    };
    

    verwenden, oder aber einfach nur andere Zeiger nehmen:

    void DoSomething( unsigned int* values, unsigned int count )
    {
        ....
    }
    
    double vals[x];
    DoSomething( (int*)vals ); // ja ich weiß, böser C-Cast, aber darum gehts nich
    

    Oder hab ich die Problematik falsch verstanden (ich befürchte fast)?


Anmelden zum Antworten