Die C++-Casts in C-Cast-Syntax // Int zu Long-Ptr casten



  • Hallo nochmal,
    nebenbei versuche ich mich gerade am Casten. Was ich mich noch frage ist, ob es für jeden C++-Cast die Möglichkeit in C gibt..
    Also zB.

    U u;
    static_cast<T>(u) // => (T)u
    reinterpret_cast<T>(u)
    dynamic_cast<T>(u)
    const_cast<T>(u)
    

    Ist mir gerade noch so in den Sinn gekommen:
    Umgekehrt, gibt es irgendwas, das man mit C-Cast machen kann, was mit C++-Cast nicht geht??
    Hängt das Cast-Verhalten in C oder C++ eigentlich vom Ursprungs- oder Zieltyp ab?

    Und noch eine kleine Frage:

    void func(long *a);
    int i;
    
    func((long*)&i); // Ist das richtig so??
      // Wird hier nicht beim Dereferenzieren
      // der Block hinter dem int noch mit ausgelesen,
      // weil ein long erwartet wird??
    
    func(&(long)i); // gefühlsmäßig hätte ich das lieber so gemacht..
    

    Also wenn der erste Fall richtig ist, kann mir dann jemand sagen was da wirklich im PC passiert?!

    MfG
    ULong



  • Ach, und kann mir jemand sagen was z.B. "cv void" bedeutet?
    Bin da jetzt schon öfters drüber gestolpert. Wofür steht cv ??


  • Mod

    Edit: Für reinterpret_cast spielt accessability natürlich keine Rolle… zu wenig Kaffee :p

    Umgekehrt, gibt es irgendwas, das man mit C-Cast machen kann, was mit C++-Cast nicht geht??

    Nein. C-Casts sind vollständig auf C++-Casts reduzierbar.

    [expr.cast]/4 schrieb:

    The conversions performed by

    • a const_cast (5.2.11),
    • a static_cast (5.2.9),
    • a static_cast followed by a const_cast ,
    • a reinterpret_cast (5.2.10), or
    • a reinterpret_cast followed by a const_cast ,

    can be performed using the cast notation of explicit type conversion. The same semantic restrictions and behaviors apply, with the exception that in performing a static_cast in the following situations the conversion is valid even if the base class is inaccessible[/b]:

    • a pointer to an object of derived class type or an lvalue or rvalue of derived class type may be explicitly converted to a pointer or reference to an unambiguous base class type, respectively;
    • a pointer to member of derived class type may be explicitly converted to a pointer to member of an unambiguous non-virtual base class type;
    • a pointer to an object of an unambiguous non-virtual base class type, a glvalue of an unambiguous non-virtual base class type, or a pointer to member of an unambiguous non-virtual base class type may be explicitly converted to a pointer, a reference, or a pointer to member of a derived class type, respectively.

    If a conversion can be interpreted in more than one of the ways listed above, the interpretation that appears first in the list is used, even if a cast resulting from that interpretation is ill-formed. If a conversion can be interpreted in more than one way as a static_cast followed by a const_cast, the conversion is ill-formed.
    [ Example:

    struct A { };
    struct I1 : A { };
    struct I2 : A { };
    struct D : I1, I2 { };
    A* foo( D* p ) {
      return (A*)( p ); // ill-formed static_cast interpretation
    }
    

    end example ]

    Dahingegen kann ein dynamic_cast natürlich mehr, als ein C-Cast, der aus einer Sprache ohne RTTI kommt.

    Wofür steht cv ??

    {}, { const }, { volatile } oder { const , volatile }.



  • Wie der Antwort von Arcoth zu entnehmen ist kann der C-Cast jedem der C++-Casts, bis auf dynamic_cast , entsprechen.

    Zu deiner anderen Frage: Du hast es schon richtig durchschaut. Beim ersten Fall mit func((long*)&i); wird wahrscheinlich mehr gelesen als eigentlich soll, zumindest falls sizeof(long) > sizeof(int) . Die zweite Variante wäre richtiger, falls man die Adressen von r-values nehmen könnte. Um es richtig zu machen, muss man eine lokale long Variable anlegen:

    long tmp = i;
    func(&tmp);
    


  • Ah, schon mal vielen Dank!
    @Arcoth: Also das muss ich mir, glaube ich, noch mal durchlesen..
    const_cast und dynamic_cast sind ja leicht zu durchschauen. Nur wann ein static_cast z.B. identisch zum reinterpret_cast ist, habe ich noch nicht so ganz raus.
    Das mit dem cv habe ich wenigstens verstanden. Ne leere Menge? Ich dachte Informatiker schreiben immer "void" 😉

    @sebi707: ..Gut dass du es sagst.. Ich bin davon ausgegangen, dass long tatsächlich länger ist als int, und habe mich gewundert, dass beim Testen hier nichts auseinander fällt...

    Also um das mal voreinander zu bekommen:
    Stimmt das erstmal so?!

    static_cast<long>(int) == reinterpret_cast<long>(int) //weil int==long
    static_cast<long>(int) != *static_cast<long*>(&int)  
     //sehe ich das richtig, dass *static_cast<A*>(&B) nie kompiliert ?? 
    *(long*)&i == reinterpret_cast<long>(int) //gilt das für alle Datentypen?
    ...
    

    Jetzt nochmal kurz zu meiner ersten Frage:

    U u; // U,T seien keine Pointer (und nur elemantare Datentypen)
    static_cast<T>(u) // ==> (T)u
    reinterpret_cast<T>(u) // irgendein Umweg über void* od allg Pointer?!? 
                           // *(T*)&u od *(T*)(void*)&u ??
    dynamic_cast<T>(u)     // hat sich erledigt
    const_cast<T>(u)       // hat sich erledigt
    

    Also ob ein Cast funktioniert, hängt ja , zumindest bei C-Casts (bei C++-Casts auch?), von der Länge des Datentyps ab (siehe long<->int). Aber wie ist das nun mit dem Datentyp an sich?
    Wenn ich das richtig verstanden habe, sind void* und char schon besonders in der Hinsicht.. Gibts da noch irgendetwas zu beachten?



  • Ach ja, und wie nennen sich eigentlich diese funktionsartigen Casts?
    int a;
    char(a);


  • Mod

    ULong schrieb:

    Ach ja, und wie nennen sich eigentlich diese funktionsartigen Casts?
    int a;
    char(a);

    Functional-style casts.

    static_cast<long>(int) != *static_cast<long*>(&int)
    

    Diese Zeile ist nicht nur ungültig sondern würde andernfalls undefiniertes Verhalten erzeugen, da du ein int Objekt mit long aliased.

    static_cast<T>(u) // ==> (T)u

    Nein, andersherum. (T)u wird auf static_cast<T>(u) reduziert.

    Also ob ein Cast funktioniert, hängt ja , zumindest bei C-Casts (bei C++-Casts auch?), von der Länge des Datentyps ab (siehe long<->int).

    Nein. Ein Cast funktioniert, wenn beide Datentypen diesen unterstützen. Die Länge macht nur (teilweise) dann einen Unterschied, wenn e.g. größere Datentypen in kleinere konvertiert werden, da dies unter Umständen zu undefiniertem Verhalten führt.



  • OK also nochmal langsam hier. Der von Arcoth verlinkte Ausschnitt erklärt wie sich der C-Cast in C++-Casts übersetzt. Nicht andersherum oder wie die C++-Casts zueinander stehen oder irgendwas. Ein static_cast macht etwas anderes als ein reinterpret_cast . Was die einzelnen C++-Casts machen kann man in jedem C++ Buch nachlesen oder auch im Internet. Dort steht dann z.B. das static_cast zwischen Pointern von verwandten Klassen konvertieren kann. Dein Beispiel *static_cast<A*>(&B) geht also wenn A von B erbt oder umgekehrt. Aber nicht zwischen long* und int* . Dafür braucht man einen reinterpret_cast .

    ULong schrieb:

    Ach ja, und wie nennen sich eigentlich diese funktionsartigen Casts?

    Nennt sich function-style cast.



  • Nennt sich function-style cast.

    😃 Also auf deutsch soviel wie "funktionsartiger Cast".. (das "Cast" lass ich mal so)
    Und wie könnte ich die mit den anderen Casts ausdrücken??

    Ist nicht so, als hätte ich mir nicht schon diverse Tutorials über Casts durchgelesen, hat mich aber offenbar auch verwirrt, und ist schon etwas her..
    Also ich hatte im Kopf, dass ein static_cast sich quasi nicht um die PC-interne Representation der Daten kümmert, im Gegensatz zum reinterpret_cast, der die Bytes nur anders benennt. (??)
    Kann man sagen, dass ein static_cast eher mathematisch, und ein reinterpret_cast eher "informatisch" ist??
    Also:
    static_cast macht aus Gurken Gurkensalat indem er sie zerschnibbelt,
    reinterpret_cast macht aus Äpfeln Gurkensalat indem er Äpfel als Gurkensalat bezeichnet.
    Kann man das so sagen!?

    Ich versuche mir gerade eine einprägsame Analogie für den Unterschied zwischen static_cast und reinterpret_castzurecht zu biegen. Für was besseres bin ich natürlich immer offen..



  • ULong schrieb:

    😃 Also auf deutsch soviel wie "funktionsartiger Cast".. (das "Cast" lass ich mal so)
    Und wie könnte ich die mit den anderen Casts ausdrücken??

    Ist äquivalent zum C-Cast.

    Mit deiner Sichtweise von static_cast und reinterpret_cast liegst du schon richtig. Mit einem static_cast kann man "sinnvolle" (wie auch immer das definiert ist) Konvertierungen durchführen. Also Beispielsweise von float nach int und dabei gehen dann die Nachkommastellen verloren.

    Der reinterpret_cast konvertiert dir (fast) jeden Pointer zu jedem anderen Pointer. Eigentlich wird auch gar nichts konvertiert sondern die bereits vorhandenen Bytes eines Typen werden als die Bytes eines völlig anderen Typens interpretiert. Je nach interner Darstellung kann da alles mögliche rauskommen.



  • Die Geschichte ist ja doch übersichtlicher als es anfangs aussah.. Also vielen Dank an alle!


Anmelden zum Antworten