[C/C++] const auf integrale typen in einer Funktion sinnvoll?
-
;fricky schrieb:
Shade Of Mine schrieb:
Es gibt nur einen cast der eine exception werfen kann: dynamic_cast. Denn alle anderen cast arten sind zur Compile Zeit validierbar. Es macht keinen Sinn dass ein static_cast oder const_cast oder reinterpret_cast eine exception wirft.
naja, wäre ja nicht schlecht, wenn reinterpret-cast und c-cast, bei absolut unsinnigen konvertierungen, auch exceptions werfen könnten. erstmal müsste sich c++ dann nicht vorwerfen lassen, schwach typisiert zu sein und zweitens wärs der stabilität der programme zuträglich. stattdessen überlässt man lieber dem OS das werfen von exceptions und der user sieht hässliche crash-meldungen.
bitte geh woanders trollen.
-
Natürlich ist const unnötig. Aber eigentlich ist das ganze Typsystem unnötig.
Aber ich bin fest davon überzeugt, dass ein striktes Typsystem für besseren Code sorgt. Und zu einem strikten Typsystem gehört für mich auch die Präzisefassung von Typeigenschaften. Sei dies nun der genaue Wertebereich oder die Konstantheit. ADA macht das hier besonders schön. In C++ ist das so aber auch möglich.
Mich nervt es immer, wenn ich Code in einer untypisierten Sprache ändere und an einer ganz anderen Stelle fliegen dann auf einmal irgend welche Laufzeittypeerrors. Bis man solche Probleme aufgelöst hat kann einige Zeit verstreichen. Aber auch in typisierten Sprachen gibt es viele Spielmöglichkeiten, wo man über so etwas stolpert. Seien das nun Sicherheitslücken durch Integeroverflows oder Werte die sich auf einmal irgend wo ändern. Sicher kommt man auch ohne aus. Aber nicht umsonst hat ADA ein derartiges Typekonzept bekommen.
-
;fricky schrieb:
naja, wäre ja nicht schlecht, wenn reinterpret-cast und c-cast, bei absolut unsinnigen konvertierungen, auch exceptions werfen könnten. erstmal müsste sich c++ dann nicht vorwerfen lassen, schwach typisiert zu sein[...]
1. C++ ist da nicht anders als C: "Ich weiß was ich tue, also compiler, lass mich einfach machen". Und nichts anderes sagt ein reinterpret_cast aus. Wenn du also explizit dem compiler den Mund verbietest, darfst du dich nicht wundern, wenn er nicht meckert.
2. Das Argument der schwachen Typisierung geht am Thema vorbei. Dabei geht es um implizite casts, nicht um die expliziten über die wir gerade reden. UND DIE HAT C AUCH.Fazit: Du argumentierst bei C++ gegen etwas, das du in C selbst verteidigst und offensichtlich gut findest.
Bist du eventuell Politiker?
-
;fricky schrieb:
naja, wäre ja nicht schlecht, wenn reinterpret-cast und c-cast, bei absolut unsinnigen konvertierungen, auch exceptions werfen könnten.
Nein. Denn reinterpret_cast heisst "vertrau mir, ich weiss was ich mache". Das darf keinen Fehler produzieren.
-
otze schrieb:
Fazit: Du argumentierst bei C++ gegen etwas, das du in C selbst verteidigst und offensichtlich gut findest.
naja, C ist nun mal sehr low-level, sowas wie 'ne portable assemblersprache. in dem bereich, in dem C verwendet wird (maschinennah, effizient, speicherschonend), muss man sich machmal über's typsystem hinwegsetzen und seltsame tricks anwenden. solche eigenschaften sind aber im high-level bereich weniger sinnvoll, weil sie einfach zu 'mächtig' sind und man sich damit über wichtige konzepte hinwegsetzen kann, an denen sprachdesigner lange getüftelt haben, um die sprache halbwegs sicher zu machen. ich würde z.b. um Java einen grossen bogen machen, wenn man da arrays in objekt-referenzen casten, einen boolean zu 'nem int addieren oder einen string überschreiben könnte.
Shade Of Mine schrieb:
;fricky schrieb:
naja, wäre ja nicht schlecht, wenn reinterpret-cast und c-cast, bei absolut unsinnigen konvertierungen, auch exceptions werfen könnten.
Nein. Denn reinterpret_cast heisst "vertrau mir, ich weiss was ich mache". Das darf keinen Fehler produzieren.
ok, dann löst eben das OS 'ne exception aus, sagte ich ja schon.
-
;fricky schrieb:
naja, wäre ja nicht schlecht, wenn reinterpret-cast und c-cast, bei absolut unsinnigen konvertierungen, auch exceptions werfen könnten. erstmal müsste sich c++ dann nicht vorwerfen lassen, schwach typisiert zu sein und zweitens wärs der stabilität der programme zuträglich. stattdessen überlässt man lieber dem OS das werfen von exceptions und der user sieht hässliche crash-meldungen.
Und wie soll entschieden werden, was sinnvoll ist und was nicht? Und wer kann den Laufzeitoverhead für so einen Schwachsinn vertreten? Abgesehen davon crashen Konvertierungen nicht, sondern höchstens der nachfolgende Zugriff.
;fricky schrieb:
naja, C ist nun mal sehr low-level, sowas wie 'ne portable assemblersprache. in dem bereich, in dem C verwendet wird (maschinennah, effizient, speicherschonend), muss man sich machmal über's typsystem hinwegsetzen und seltsame tricks anwenden. solche eigenschaften sind aber im high-level bereich weniger sinnvoll, weil sie einfach zu 'mächtig' sind und man sich damit über wichtige konzepte hinwegsetzen kann, an denen sprachdesigner lange getüftelt haben, um die sprache halbwegs sicher zu machen. ich würde z.b. um Java einen grossen bogen machen, wenn man da arrays in objekt-referenzen casten, einen boolean zu 'nem int addieren oder einen string überschreiben könnte.
C++ hat eben den Vorteil, dass man genauso Low-Level arbeiten kann, und zwar ohne Einschränkungen. Wenn man auf hohem Abstraktionslevel entwickelt, braucht man sowas wie
reinterpret_cast
kaum, wieso also eine Exception?;fricky schrieb:
ok, dann löst eben das OS 'ne exception aus, sagte ich ja schon.
Du hast wohl Exceptions nicht ganz verstanden. Die sind nämlich nicht primär dazu da, sämtliche Programmlogikfehler zu beheben. Bei
reinterpret_cast
macht ein "Rumprobieren, wenns schief läuft, fliegt eine Exception" wenig Sinn. Ein fehlerhaft eingesetztesreinterpret_cast
ist nahezu immer ein Programmierfehler, der auch zur Laufzeit nicht vernünftig behoben werden kann. Man lässt das Programm lieber crashen und passt den Code so an, dass er funktioniert.P.S.: Das, was rüdiger angetönt hat, ist eins der Standardargumente gegen C++ - "man brauchts nicht". Klar, ist wunderbar anwendbar auf Mehrfachvererbung, Operatorüberladung, Zeigerarithmetik, Const-Correctness und sonst alle C++-Features, die andere Sprachen nicht bieten "und ja auch ohne auskommen". Das ideale Argument
, was will man mehr?
-
Nexus schrieb:
;fricky schrieb:
naja, wäre ja nicht schlecht, wenn reinterpret-cast und c-cast, bei absolut unsinnigen konvertierungen, auch exceptions werfen könnten. erstmal müsste sich c++ dann nicht vorwerfen lassen, schwach typisiert zu sein und zweitens wärs der stabilität der programme zuträglich. stattdessen überlässt man lieber dem OS das werfen von exceptions und der user sieht hässliche crash-meldungen.
Und wie soll entschieden werden, was sinnvoll ist und was nicht? Und wer kann den Laufzeitoverhead für so einen Schwachsinn vertreten? Abgesehen davon crashen Konvertierungen nicht, sondern höchstens der nachfolgende Zugriff.
vielleicht konfigurierbar über'n compiler-switch oder so. RTTI lässt sich ja auch ein- und ausschalten. klar können konvertierungen auch schon selber abschmieren. dazu brauchte noch nicht mal 'nen dynamic cast, der sich durch die vererbungsliste hangelt und plötzlich auf einen 0-pointer trifft.
Nexus schrieb:
C++ hat eben den Vorteil, dass man genauso Low-Level arbeiten kann, und zwar ohne Einschränkungen.
doch mit einschränkungen: http://www.mikrocontroller.net/articles/C_vs_C-Plusplus
Nexus schrieb:
P.S.: Das, was rüdiger angetönt hat, ist eins der Standardargumente gegen C++ - "man brauchts nicht". Klar, ist wunderbar anwendbar auf Mehrfachvererbung, Operatorüberladung, Zeigerarithmetik, Const-Correctness und sonst alle C++-Features, die andere Sprachen nicht bieten "und ja auch ohne auskommen". Das ideale Argument
, was will man mehr?
aber im prinzip stimmt es, z.b:
mehrfachvererbung -> sehr selten sinnvoll, fördert schlechtes design
operatorüberladung -> geringer nutzen, wird oft falsch verwendet
zeiger/zeigerarithmetik -> in low-level sprachen sinnvoll, in höheren sprachen nicht
const-correctness -> idiomatisch in C++, in der realität ausserhalb von c++ aber ohne bedeutung.
-
;fricky schrieb:
aber im prinzip stimmt es, z.b:
mehrfachvererbung -> sehr selten sinnvoll, fördert schlechtes design
operatorüberladung -> geringer nutzen, wird oft falsch verwendet
zeiger/zeigerarithmetik -> in low-level sprachen sinnvoll, in höheren sprachen nicht
const-correctness -> idiomatisch in C++, in der realität ausserhalb von c++ aber ohne bedeutung.
Ach, halt doch einfach die Klappe. Du hast keinen Schimmer von C++ und Deine Aussagen sind größtenteils falsch.
-
;fricky schrieb:
Nexus schrieb:
C++ hat eben den Vorteil, dass man genauso Low-Level arbeiten kann, und zwar ohne Einschränkungen.
doch mit einschränkungen: http://www.mikrocontroller.net/articles/C_vs_C-Plusplus
Der Link war wohl ein Eigentor, zumindest sehe ich hier keinen einzigen Nachteil von C++ gegenüber C. In allen aufgezählten Punkten ging C++ als Sieger hervor in Bezug darauf, dass es Funktionalität liefert die man in C händisch nachbauen muss oder gar nicht hat. Und was ganz wichtig ist: wenn man sie nicht benutzt, dann kosten sie nichts.
-
;fricky schrieb:
klar können konvertierungen auch schon selber abschmieren.
EPIC fail.
reinterpret_cast kann nicht abschmieren.gib dir bitte mühe beim trollen, mittlerweile kann meine oma deine "argumente" widerlegen... uU vl mal mit der materie befassen...?
-
Shade Of Mine schrieb:
reinterpret_cast kann nicht abschmieren.
cast in einen Typ, für den der Operand nicht hinreichend ausgerichtet ist?
-
camper schrieb:
Shade Of Mine schrieb:
reinterpret_cast kann nicht abschmieren.
cast in einen Typ, für den der Operand nicht hinreichend ausgerichtet ist?
Dann schmiert der Zugriff ab, oder?
-
Shade Of Mine schrieb:
reinterpret_cast kann nicht abschmieren.
probier dies:
int a = 0; puts ("hallo-1"); int &b = *reinterpret_cast<int*>(a); // hier puts ("hallo-2"); char *c = reinterpret_cast<char*>(b); // oder hier puts ("hallo-3");
-
Shade Of Mine schrieb:
camper schrieb:
Shade Of Mine schrieb:
reinterpret_cast kann nicht abschmieren.
cast in einen Typ, für den der Operand nicht hinreichend ausgerichtet ist?
Dann schmiert der Zugriff ab, oder?
Der Standard ist hier etwas mehrdeutig formuliert.
5.2.10/7
A pointer to an object can be explicitly converted to a pointer to an object of different type.65) Except that converting an rvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified.Beschränkt die in Klammern genannte Bedingung nur die Gleichheit der Konvertierungskette T1*->T2*->T1* oder ist die ausreichende Ausrichtung eine Voraussetzung, damit die Konvertierung überhaupt ein definiertes Ergebnis hat?
C90 schrieb:
6.3.4
...
A pointer to an object or incomplete type may be converted to a pointer to a different object type or a different incomplete type. The resulting pointer might not be valid if it is improperly aligned for the type pointed to. It is guaranteed, however, that a pointer to an object of a given alignment may be converted to apointer to an object of the same alignmet or a less strict alignmet and back again: the result shall compare equal to the original pointer.Was ein "invalid pointer" sein soll, ist wahrscheinlich nirgendwo definiert.
C99 schrieb:
6.3.2.3
7 A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned57) for the pointed-to type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.wenigstens diese Formulierung ist eindeutig - fraglich nur, ob man sie übertragen darf...
-
;fricky schrieb:
probier dies:
epic fail.
reinterpret_cast schmiert nicht ab. der zugriff danach schmiert ab.
-
Shade Of Mine schrieb:
reinterpret_cast schmiert nicht ab. der zugriff danach schmiert ab.
es wird doch nirgends zugegriffen, nur umgewandelt.
-
;fricky schrieb:
es wird doch nirgends zugegriffen, nur umgewandelt.
Dann lern mal c++
int &b = *reinterpret_cast<int*>(a);
ich sehe hier eine dereferenzierung des gecasteten wertes.char *c = reinterpret_cast<char*>(b);
ich sehe hier einen zugriff auf das gecastete objekt von vorher.
-
;fricky schrieb:
Shade Of Mine schrieb:
reinterpret_cast schmiert nicht ab. der zugriff danach schmiert ab.
es wird doch nirgends zugegriffen, nur umgewandelt.
Siehst du, du solltest wirklich einmal die Syntax und Semantik von C++ lernen, bevor du argumentieren willst. Wenn du in C++ programmierst, wie oben, dann präsentierst du das typische Bild eines Fricklers, der einfach so lange rumhackt bis der Compiler irgendwie das gewünschte ausspuckt. Mit einem sauberen C++ Programm hat das nichts gemeinsam.
-
Shade Of Mine schrieb:
int &b = *reinterpret_cast<int*>(a);
ich sehe hier eine dereferenzierung des gecasteten wertes.char *c = reinterpret_cast<char*>(b);
ich sehe hier einen zugriff auf das gecastete objekt von vorher.b ist eine referenz, a muss nicht dereferenziert werden weil int& und int* äquivalent sind. selbiges bei b nach c, umwandlung von referenz in zeiger.
hast du es ausprobiert? wo stürzt es bei dir ab? eigentlich sollte nichts passieren.
-
;fricky schrieb:
b ist eine referenz, a muss nicht dereferenziert werden weil int& und int* äquivalent sind. selbiges bei b nach c, umwandlung von referenz in zeiger.
hast du es ausprobiert? wo stürzt es bei dir ab? eigentlich sollte nichts passieren.
Grundlagen lernen fricky.
Natürlich sollte etwas passieren.
Bei der 1. dereferenzierung wird nichts passieren, da eine referenz intern ein zeiger ist, bei der dereferenzierung in dem 2. cast macht es aber peng, da ein null zeiger dereferenziert wird.oh wunder.
kann ich dir ohne testen sagen.
du hast in jedem reinterpret_cast nunmal einen zugriff auf einen gecasteten wert. und das funktioniert nicht. der zugriff schmiert ab, nicht der cast.
ist auch leicht testbar:
int a = 0; puts("hallo-1"); int* b = reinterpret_cast<int*>(a); puts("hallo-2"); int& b2=*b; puts("hallo-3"); int b3=b2; puts("hallo-4"); char *c = reinterpret_cast<char*>(b3); puts("hallo-5");
und schon schmiert es bei der zuweisung
int b3=b2;
ab.keine magie, keine hexerei.