char * als char const *&
-
Baltram schrieb:
[...] habe an einer Stelle das Problem, dass mein Code unsagbar hässlich ist, weil ich eine eigentlich harmlose Typumwandlung ohne const_cast nicht hinbekomme: Von 'char *' nach 'char const *&'.
So eine Konvertierung ist nicht harmlos. Würde das ohne const_cast funktionieren, wäre es eine Lücke im const-System:
const char foo = 23; char* ptr = 0; char const* &ref = ptr; // (*) ref = &foo; // oops! ptr (ein zeiger auf nicht-const!) zeigt jetzt auch auf foo!!! *ptr = 42; // oops! Der Versuch, foo zu ändern ruft undefiniertes Verhalten hervor!Deswegen akzeptiert der Compiler so etwas wie in Zeile 3 (*) nicht ohne const_cast.
-
Also deine Antwort verstehe ich jetzt nicht, krümelkacker. Er will doch const hinzucasten, wenn ich das richtig sehe.
-
314159265358979 schrieb:
Also deine Antwort verstehe ich jetzt nicht, krümelkacker. Er will doch const hinzucasten, wenn ich das richtig sehe.
Das const bezieht sich aber nur auf den "Pointee" (auf das gezeigte), nicht aber auf den Zeiger selbst. Den Zeiger könnte man also noch über die Referenz ändern und damit so etwas wie einen versteckten const-cast durchführen. Ich finde das Beispiel einleuchtend. Was verstehst Du daran nicht?
Hier nochmal quasi das Gleiche mit Zeigern:
char * * p = ...; char * const * q = p; // OK char const * * r = p; // Fehler! (da "const-Lücke") char const * const * z = p; // OK (hier kann nichts schief gehen)Würde bei 'r' der Compiler nicht streiken, könnte man damit const-Correctness ohne const_cast umgehen.
-
krümelkacker schrieb:
Hier nochmal quasi das Gleiche mit Zeigern:
char * * p = ...; char * const * q = p; // OK char const * * r = p; // Fehler! (da "const-Lücke") char const * const * z = p; // OK (hier kann nichts schief gehen)Würde bei 'r' der Compiler nicht streiken, könnte man damit const-Correctness ohne const_cast umgehen.
Ich versteh es auch nicht. Was kann man da umgehen? An "char * * p" ist doch garnichts const?
-
Noch etwas: das
char tempChar = *end; *end = 0; // Der Deferenzierungsoperator muss weggeht nicht, da
endnicht auf eine gültige Adresse zeigt. Die Folge der Dereferenzierung eines nicht initialisierten Zeigers könnte alles Mögliche sein. Welchen Compiler verwendest du? Normalerweise müsste er einen Run-time Check Error werfen.Edit: oh, habe übersehen, dass es VS05 ist. Der müsste aber solche Checks machen..
-
[Rewind] schrieb:
Noch etwas: das
char tempChar = *end; *end = 0; // Der Deferenzierungsoperator muss weggeht nicht, da
endnicht auf eine gültige Adresse zeigt. Die Folge der Dereferenzierung eines nicht initialisierten Zeigers könnte alles Mögliche sein. Welchen Compiler verwendest du? Normalerweise müsste er einen Run-time Check Error werfen.Edit: oh, habe übersehen, dass es VS05 ist. Der müsste aber solche Checks machen..
Quatsch, natürlich soll end hier auf eine gültige Adresse zeigen. (Auch wenn das nicht garantiert ist, da die detectString Funktion überhaupt nicht auf das Ende des Strings achtet.)
-
Jetzt sehe ich auch, dass es davor durch die Funktion geändert wird. Ich nehme es zurück.
-
Ich verstehs immer noch nicht. Wenn ich ein const hinzufüge, kann doch nichts schiefgehen.

-
cooky451 schrieb:
(Auch wenn das nicht garantiert ist, da die detectString Funktion überhaupt nicht auf das Ende des Strings achtet.)
"Original" achtet sie auf alle white-space characters und auf 0, hab's nur vereinfacht für hier.
314159265358979 schrieb:
Ich verstehs immer noch nicht. Wenn ich ein const hinzufüge, kann doch nichts schiefgehen.

Hier füge ich const hinzu und es geht was schief:
void setzeGleich( char const *& a, char const * b ) { a = b; } int main() { char const text[] = "Unveränderbar"; char * textPtr; setzeGleich( textPtr, text ); // Geht nicht, obwohl "nur" const bei 'textPtr' hinzugefügt wird. textPtr[ 0 ] = ' '; textPtr[ 1 ] = ' '; // 'text' ist jetzt " veränderbar". }
-
wert56zui schrieb:
krümelkacker schrieb:
Hier nochmal quasi das Gleiche mit Zeigern:
char * * p = ...; char * const * q = p; // OK char const * * r = p; // Fehler! (da "const-Lücke") char const * const * z = p; // OK (hier kann nichts schief gehen)Würde bei 'r' der Compiler nicht streiken, könnte man damit const-Correctness ohne const_cast umgehen.
Ich versteh es auch nicht. Was kann man da umgehen? An "char * * p" ist doch garnichts const?
Das Beispiel soll auch nur zeigen, welche Konvertierungen von C++ erlaubt werden und welche nicht.
314159265358979 schrieb:
Ich verstehs immer noch nicht. Wenn ich ein const hinzufüge, kann doch nichts schiefgehen.

Wenn Du es einfach irgendwo hinzufügen könntest, ja. Da könnte dann was schiefgehen.
Wäre die Stelle mit 'r' erlaubt, könnte man ohne const_cast folgendes machen:
char * z = 0; char const * * r = &z; const char k = 23; *r = &k; // Upps! z (vom Typ [b]char*[/b]) zeigt jetzt auf k (vom Typ [b]const char[/b]) // Und das passierte ohne const_cast !!!T** -> T const** ist deswegen nicht erlaubt.
T** -> T const*const* ist aber erlaubt. (hier kann nichts schief gehen)
T** -> T*const* auch. (hier kann nichts schief gehen)Das Problem des Threaderstellers ist genau das Gleiche mit 'ner Referenz auf oberster Ebene. Und dazu hatte ich auch schon ein Beispiel gezeigt.
Vielleicht muss ich noch deutlicher werden. Wenn man einfach irgendwo ein const hinzufügen dürfte, bräuchten wir kein const_cast mehr, denn dann könnten wir uns const_cast einfach selbst bauen:
template<class T> T* mach_weg_dat_const(T const* param) { T* q; const T** r = &q; // <-- gut, dass das hier nicht wirklich kompiliert! *r = param; // q zeigt auf *param aber das const ist plötzlich weg!!! return q; }