Konvertierung vs. Cast
-
Gugelmoser schrieb:
Abend,
hab 2 kleine Fragen:Ist ein Cast nach unsigned immer wohl definiert? Bsp:
unsigned char uc = -99; // OK? uc = 555; // OK?Es handelt sich nicht um Casts. Das Ergebnis ist immer wohldefiniert (4.7/2), sofern der Ausgangsausdruck einen integralen oder (unscoped - we übersetzt man das?) Aufzählungstypen hat. Hat der Ausgangsausdruck einen Gleitkommatypen wird es undefiniert, sobald der abgeschnittene Ausgangswert nicht mehr im Zieltypen darstellbar ist (4.8/1).
Gugelmoser schrieb:
Ist ein Cast nach signed nur dann definiert, wenn der Wert im Zieltyp darstellbar ist, ansonsten UB? Bsp:
signed char sc = -99; // OK? sc = 555; // UB?Auch diese Konvertierung ist, wenn der Ausgangstyp ein integraler bzw. (unscoped) Aufzählungstyp ist, immer definiert (4.7/3). Allerdings ist das konkrete Ergebnis implementation-defined, falls der Ausgangswert nicht exakt im Zieltypen darstellbar ist. Für Gleitkommawerte gilt das Gleiche wie oben.
Das ist im Übrigen - was man vermutlich leicht verwechseln kann - eine andere Frage als die, was passiert, wenn der Wert einer Berechnung den Wertebereich des jeweiligen Typen, mit dem die Berechnung ausgeführt wird.
-
camper schrieb:
Es handelt sich nicht um Casts.
Wann spricht man den von einem Cast. Kann einer ein Beispiel machen.

camper schrieb:
Allerdings ist das konkrete Ergebnis implementation-defined, falls der Ausgangswert nicht exakt im Zieltypen darstellbar ist.
Dass nennt man dann ja UB, oder bin ich nun aufm falschen Dampfer?
-
Gugelmoser schrieb:
camper schrieb:
Es handelt sich nicht um Casts.
Wann spricht man den von einem Cast. Kann einer ein Beispiel machen.

Beispiele für casts:
/* ... */ class B; class D : public B {}; void f(const int& ci) { int i; long l; int* pi; char ca[sizeof(int)]; i = static_cast<int>(l); i = (int)l; //C-Style cast i = int(l); //function style cast; pi = const_cast<int*>(&ci); pi = (int*)(&ci); //C-Style cast pi = reinterpret_cast<int*>(ca); pi = (int*)(ca); //C-Style cast B* pb; D* pd; pd = dynamic_cast<D*>(pb); pd = (D*)pb; //Tut nicht das gleiche!!Gugelmoser schrieb:
camper schrieb:
Allerdings ist das konkrete Ergebnis implementation-defined, falls der Ausgangswert nicht exakt im Zieltypen darstellbar ist.
Dass nennt man dann ja UB, oder bin ich nun aufm falschen Dampfer?
Implementation defined != undefined.
-
pumuckl schrieb:
class B; class D : public B {}; void f(const int& ci) { int i; long l; int* pi; char ca[sizeof(int)]; i = static_cast<int>(l); i = (int)l; //C-Style cast i = int(l); //function style cast; pi = const_cast<int*>(&ci); pi = (int*)(&ci); //C-Style cast pi = reinterpret_cast<int*>(ca); pi = (int*)(ca); //C-Style cast B* pb; D* pd; pd = dynamic_cast<D*>(pb); pd = (D*)pb; //Tut nicht das gleiche!!Ok, also es sieht für mich nun so aus, als spräche man von einem Cast, wenn ein C++ Cast-Operator, ein C-Style cast oder ein function-style-cast zum Einsatz kommt? Aber ich hab noch immer nicht verstaden wo der Unterschied zwischen Cast und Konvertierung liegt.
-
Ich habe noch ein bisschen recherchiert und möchste nun noch eine Zusammenfassung posten, um anderen Anfängern zu helfen. Falls Missverständnisse oder Fehler enhalten sind, möge mich bitte jemand korrigieren.
Automatische (implizite) Typ-Konvertierung
Findet immer dann statt, wenn der Compiler ein Datum eines bestimmten Typs erwartet, jedoch ein Datum eines anderen Typs gegeben ist, sodass der Compiler nun eine implizite Typ-Konvertierung durchführt. Es gibt 2 Arten von impliziter Typ-Konvertierung bei numerischen Typen:1. numeric promotion:
- Integral-Value: bool, char, signed char, unsigned char, short, unsigned short ----> promoted to int oder unsigned int, falls int den Wert nicht darstellen kann.
- Fließkomma-Value: float-value ----> promoted to double-value.
2. numeric conversion: Nachdem numeric promotion gemacht wurde, kann das Datum in einen anderen nummerischen Typ konvertiert werden.
- Ein Datum eines integralen Typs (und auch ein Enumerator) kann zu jedem anderen integralen Typ konvertiert werden. Bei der Konvertierung zu einem signed-integral kann es zu einem Überlauf kommen. Das Ergebnis ist dann implementation-defined.
- Ein Datum eines fließkomma Typs kann zum anderen fließkomma Typ konvertiert werden. Falls das zu konvertierende Datum im anderen fließkomma Typ exakt dargestellt werden kann, findet eine exakte Konvertierung statt. Ansonsten, wenn zwei Daten möglich sind und das ursprüngliche Datum zwischen den beiden liegt, wird irgendeins von beiden genommen. Alles andere ist implementation-defined.
- Ein Datum eines integralen Typs kann zu einem fließkomma Typ konvertiert werden. Falls möglich ist das Ergebnis exakt, ansonsten wird der nächst höhere oder nächst kleinere darstellbare Wert genommen (implementation-defined).
- Ein Datum eines fließkomma Typs kann zu einem integralen Typ konvertiert werden, wobei die Nachkommastellen verworfen werden.
Explizite Typ-Konvertierung (Cast)
Es gibt Fälle, bei denen eine implizite Typ-Konvertierung schlicht nicht durchführbar ist oder der Compiler sich nicht sicher ist, zu welchem Typ er konvertieren soll. Diese Fälle benötigen eine explizite Anweisung vom Programmierer an den Compiler, ansonsten Compilerfehler. In C++ wurden 4 Cast-Operatoren eingeführt, die eine anschauliche Syntax mit Aussagekraft und Typsicherheit bieten. Der Compiler versucht den Ausdruck dann so zu interpretieren, als wäre er von dem angegebenen Typ; falls ihm dies nicht gelingt, gibt es einen Compilerfehler.static_cast<typ>(ausdruck); // Eigentlich ist nur der static_cast sinnvoll. dynamic_cast<typ>(ausdruck); // Weist auf Designfehler hin, d.h. ein schlechtes Design ist der Grund, dass man dynamic_cast braucht. const_cast<typ>(ausdruck); // const_cast zur Umgehung von Compilerfehlern einzusetzen kann ja nur gefährlich sein. Man soll sich also // im Vorfeld überlegen, ob man nun const will oder nicht, und die Deklaration dann gleich richtig machen. reinterpret_cast<typ>(ausdruck);// Sehr gefährlich. Wenn man nicht exakt weiß was man tut, landet man schnell bei undefined behaviour.Hinweis
Wenn hustbaer nichts dagegen hat, darf ich ihn einmal zitieren:hustbaer schrieb:
Klar gibt es casting Operatoren, aber die kann man nicht überladen und auch nicht definieren, die sind einfach eingebaut.
Das was man definieren kann nennt sich "conversion operator".
-
Du hast noch weitere implizite Konvertierungen vergessen, nämlich implizite Konvertierung durch nutzerdefinierte, nicht mit explicit gekennzeichnete Konvertierungsoperatoren bzw. -konstruktoren, Konvertierung von Pointern nach bool, von T* nach void*, von 0 nach T*, von derived* nach base* usw.
-
pumuckl schrieb:
Du hast noch weitere implizite Konvertierungen vergessen, nämlich implizite Konvertierung durch nutzerdefinierte, nicht mit explicit gekennzeichnete Konvertierungsoperatoren bzw. -konstruktoren, Konvertierung von Pointern nach bool, von T* nach void*, von 0 nach T*, von derived* nach base* usw.
Ich weiß
Aber mir ging es nur darum, zu verstehn warum die Aussagen "manueller Cast" und "automatischer Cast" falsch sind. Ich glaube ich bin nicht der einzige, der diese benutzt hat. Ich frage mich gerade, wieso das so ist. Weiß da einer eine Antwort?In den Skripts von meinem Prof. ist auch immer die Rede von automatischen und manuellen Casts und die unterrichten immer ein c c++ gemisch. Langsam glaub ich die haben alle solche Bücher wie "C++ von A bis Z". Bitter
-
Gugelmoser schrieb:
Ich weiß
Aber mir ging es nur darum, zu verstehn warum die Aussagen "manueller Cast" und "automatischer Cast" falsch sind. Ich glaube ich bin nicht der einzige, der diese benutzt hat. Ich frage mich gerade, wieso das so ist. Weiß da einer eine Antwort?Cast ist eben ein Synonym für explizite Typkonvertierung. Entweder eines der vier C++-Operatorschlüsselwörter, oder C-Casts oder Function-Style-Casts wie z.B.
short(3).
-
Nexus schrieb:
Gugelmoser schrieb:
Ich weiß
Aber mir ging es nur darum, zu verstehn warum die Aussagen "manueller Cast" und "automatischer Cast" falsch sind. Ich glaube ich bin nicht der einzige, der diese benutzt hat. Ich frage mich gerade, wieso das so ist. Weiß da einer eine Antwort?Cast ist eben ein Synonym für explizite Typkonvertierung. Entweder eines der vier C++-Operatorschlüsselwörter, oder C-Casts oder Function-Style-Casts wie z.B.
short(3).Jup schon, aber ich höre immer noch oft impliziter Cast.
Wie ist den eure Erfahrung so mit C++ Dozenten?
-
Gugelmoser schrieb:
Wie ist den eure Erfahrung so mit C++ Dozenten?
Habe ich nicht. Meine Dozenten bestanden aus Papier oder PDFs & Co., und offenbar hatte ich das Glück gleich an die Richtigen geraten zu sein - Herb Sutter, Scott Meyers, Andrei Alexandrescu & Co.
Zum Thema Cast und Konvertierung: Nach ein wenig umherschauen im Netz meine ich, die allgemeine Verwendung von "cast" und "conversion" in etwa so verstanden zu haben: "Cast" wird benutzt, wenn ein Ausdruck eines Typs an einer Stelle benutzt wird, an der ein Ausdruck eines anderen Typs benötigt wird. Ein Cast ist daher immer explizit und benötigt eine Umwandlung (conversion), die entweder explizit (cast-Operatoren, C-Cast, function-style-cast) oder implizit (diverse Möglichkeiten...) vonstatten gehen kann. Ein Cast ist das, was syntaktisch im Quellcode passiert, eine Conversion ist im Grunde das, was der Compiler macht, eben entweder automatisch/implizit, oder indem ´man ihn dazu anweist.