Konvertierungen


  • Mod

    Aufgrund int() hat man 3. 3 / 2 = 1.5

    Wenn Fließkommazahlen in integrale Typen konvertiert werden, wird der Nachkommateil einfach "abgeschnitten", sprich die Division ist 3 / 2, das ist 1.5. Und da der Typ des Divisionsausdrucks wieder integral ist, wird der Nachkommateil abgeschnitten, und es ergibt sich 1.

    Darum bleibt es beim float-Wert 1.5?

    Jup.



  • Danke 🙂

    Und wie schaut es mit diesen Konvertierungsfunktionen int() und float() aus? Sind die in C++11 deprecated?



  • Ich weiß nicht, ob die casts schon per Standard deprecated sind. Allerdings wird von ihnen angeraten. Nimm stattdessen einfach static_cast.



  • tröröö schrieb:

    Sind die in C++11 deprecated?

    Nein, sie sind auch in C++98 nícht deprecated.
    Man sollte sie nur nicht verwenden. Um mal eben einen float zu einem int zu machen, ist das ok, aber auf gar keinen Fall verwenden wenn Pointer oder UDTs beteiligt sind.



  • Ok, danke 🙂


  • Mod

    Nathan schrieb:

    Um mal eben einen float zu einem int zu machen, ist das ok, aber auf gar keinen Fall verwenden wenn Pointer oder UDTs beteiligt sind.

    std::string("asdf")
    


  • Arcoth schrieb:

    Nathan schrieb:

    Um mal eben einen float zu einem int zu machen, ist das ok, aber auf gar keinen Fall verwenden wenn Pointer oder UDTs beteiligt sind.

    std::string("asdf")
    

    Arcoth, das ist ein Konstruktoraufruf. Kein cast.



  • Nathan schrieb:

    Arcoth schrieb:

    std::string("asdf")
    

    Arcoth, das ist ein Konstruktoraufruf. Kein cast.

    Hätte ich auch gesagt. Scott Meyers sagt in Effective C++ allerdings dass das ein Cast ist.

    #include <iostream>
    #include <string>
    
    int main(){
    	std::cout << (std::string)"hello";
    	std::cout << static_cast<std::string>("world");
    }
    

    Ideone

    Scheinbar ist das aus C++-Sicht dasselbe.



  • Dann kanns nur eine Konstruktoraufrufcast sein.



  • T(exp) ist der sog. "function style cast". Der gleich mächtig ist wie der C-style Cast.
    Leider:

    typedef void* VoidPtr;
    int main()
    {
        int i = 123;
        VoidPtr v = VoidPtr(i); // OK, das selbe wie (VoidPtr)i
        return 0;
    }
    

    Die Schreibweise ansich ist ja OK, aber dass man damit alles machen kann was ein C-style Cast auch macht, finde ich schon etwas übertrieben.


  • Mod

    Nathan schrieb:

    Arcoth, das ist ein Konstruktoraufruf. Kein cast.

    Das ist Identisch. Du castest einen char const* nach std::string . Was denkst du, was ein Cast ist?



  • Arcoth schrieb:

    Nathan schrieb:

    Arcoth, das ist ein Konstruktoraufruf. Kein cast.

    Das ist Identisch. Du castest einen char const* nach std::string . Was denkst du, was ein Cast ist?

    Ja, das Prinzip ist das ähnliche.
    Aber bei std::string("foo") wird C++-Code aufgerufen, der sicher geschrieben wurde und fehlergeprüft sind.
    Wohingegen die Casts im eigentlichem Sinne u.U. irgendwelche Bitumrepräsentation sind.


  • Mod

    Nathan schrieb:

    Wohingegen die Casts im eigentlichem Sinne u.U. irgendwelche Bitumrepräsentation sind.

    static_cast<double>(int_wert)
    

  • Mod

    Nathan schrieb:

    Wohingegen die Casts im eigentlichem Sinne u.U. irgendwelche Bitumrepräsentation sind.

    Schon wenn du nur einen unsigned zu int castest, kann keine simple Bitumrepräsentation am Werk sein.

    Ja, das Prinzip ist das ähnliche.

    Nein, es ist haargenau das gleiche. Ein Cast ist eigentlich nur eine Erstellung und Initialisierung einer Temporary mit dem gegebenen Operanden.
    Edit:

    N3797 §5.2.3/1 schrieb:

    the expression T(x1, x2, ...) is equivalent in effect to the declaration T t(x1, x2, ...); for some invented temporary variable t, with the result being the value of t as a prvalue.



  • Arcoth schrieb:

    Nein, es ist haargenau das gleiche. Ein Cast ist eigentlich nur eine Erstellung und Initialisierung einer Temporary mit dem gegebenen Operanden.
    Edit:

    N3797 §5.2.3/1 schrieb:

    the expression T(x1, x2, ...) is equivalent in effect to the declaration T t(x1, x2, ...); for some invented temporary variable t, with the result being the value of t as a prvalue.

    Nein, es ist nicht haargenau das gleiche. In deinem Zitat gibt es mehrere Parameter, und damit kann es schon kein Cast mehr sein.
    Mit nur einem Parameter ist es aber ein Cast, und nicht mehr äquivalent zu der anderen Form.

    Siehe:

    typedef void* VoidPtr; 
    
    int main() 
    { 
         int i = 123; 
         VoidPtr v = VoidPtr(i); // OK, das selbe wie (VoidPtr)i 
         VoidPtr v2(i); // Fehler
         return 0; 
    }
    

    Ein Konstruktor-Aufruf ist ein Funktionsaufruf (*), und ein Funktionsaufruf kann keinen reinterpret_cast machen. Ein Function-Style-Cast dagegen schon.

    Hatte ich eigentlich schon geschrieben - wenn du aufgepasst hättest...

    EDIT:
    *: OK, vermutlich formal nicht. Aber was diesen Fall angeht so-gut-wie 😉



  • SeppJ schrieb:

    Nathan schrieb:

    Wohingegen die Casts im eigentlichem Sinne u.U. irgendwelche Bitumrepräsentation sind.

    static_cast<double>(int_wert)
    

    u.U. steht für unter Umständen, da sind das jetzt irgendwelches Assemblerbefehle.


  • Mod

    Nathan schrieb:

    u.U. steht für unter Umständen, da sind das jetzt irgendwelches Assemblerbefehle.

    Zeig mal einen static_cast, der eine rein logische Uminterpretation von Bits, ohne jede Repräsentation im erzeugten Maschinencode, ist. Du denkst an reinterpret_cast.

    P.S.: Ok, ein paar fallen mir selber ein: Ein Typ nach sich selbst. char nach signed/unsigned char (passendes Vorzeichen wählen). Aber neben den trivialen Beispielen tut der static_cast in der Regel etwas. Das er "unter Umständen" auch mal nichts tut (also nichts auf Ebene des erzeugten Codes), ist nicht seine definierende Eigenschaft. Ein Konstruktoraufruf ist "unter Umständen" auch nur eine Uminterpretation.



  • Typ& auf ErsteBasisklasse&
    Typ* auf ErsteBasisklasse*
    ErsteBasisklasse& auf Typ&
    ErsteBasisklasse* auf Typ*
    Mit vielen Compilern ist auch char -> short, short -> int u.Ä. ein Nop (weil der Wert sowieso schon in einem Register mit voller Breite steht).

    ----

    Und wieso wird hier von allen der Reinterpret-Cast ignoriert?

    Nochmal: das was man über T(exp) wissen sollte, ist dass es dem C-Style-Cast gleichgestellt ist, und daher nen Reinterpret-Cast machen kann.
    Einself.

    EDIT: Ach, OK, sehe grade... um T(exp) ging's erst zuletzt. Auch gut 🙂



  • SeppJ schrieb:

    Nathan schrieb:

    u.U. steht für unter Umständen, da sind das jetzt irgendwelches Assemblerbefehle.

    Zeig mal einen static_cast, der eine rein logische Uminterpretation von Bits, ohne jede Repräsentation im erzeugten Maschinencode, ist. Du denkst an reinterpret_cast.

    Ja, ich denk an reinterpret_cast. Ich schrieb allgemein von casts, deshalb auch reinterpret_cast.

    Edit: Und das Ganze hier ist auch der Grund, wieso ich lang überlegt hab, bevor ich meinen ersten Beitrag schrieb...



  • cout << fval1/ival2 << '\n'; // => 1.75
    cout << int(fval1)/ival2 << '\n'; //  => 1
    cout << int(fval1)/float(ival2) << '\n'; //  => 1.5
    

    Der Jürgen Wolf und ich sind ein paar (waren nur ein paar wenige und keine spektakulären) Punkte aus einem Buch durchgegangen, die mir aufgefallen sind. Das mit dem int() und float() wird er auch noch ändern in die neuen C++11-Konvertierungsfunktionen. Also ich finde, der ist echt nett. Er kümmert sich um die Leser und auch um sein neues Buch 🙂 Hackt doch bitte nicht immer auf ihm rum. Schaut euch sein neues Buch "Grundkurs C++ Aktuell zu C++11" doch mal an (müsst es ja nicht gleich kaufen). Also für mich als Einsteiger ist dieses Buch super. Ich bin zufrieden damit. 🙂

    Ach übrigens: danke für die vielen Einträge. Muss ich jetzt gleich mal alle durchlesen ...


Anmelden zum Antworten