Nach Ссылка hat diese Funktion eine Signatur von long int strtol (const char* str, char** endptr, int base)
.
Ich frage mich jedoch: Wenn es eine const char *
an den Anfang der Zeichenfolge übergeben wird, wie schafft es es, diese in einen nicht-constant Zeiger auf das erste unverarbeitete Zeichen zu verwandeln, ohne zu betrügen? Wie würde eine Implementierung von strtol aussehen, die keine const_cast ausführt?
Wie implementieren Sie
strtol
unter const-correctness?
Das tun Sie nicht, weil die Definition von strtol
inhärent nicht const
-korrekt ist.
Dies ist ein Fehler in der C-Standardbibliothek.
Es gibt mehrere Standardfunktionen, die ein const char*
Argument (das den Anfang eines Zeichenarrays angibt) verwenden und einen nicht const
char*
Zeiger zurückgeben, der zum Ändern dieses Arrays verwendet werden kann.
strchr
ist ein Beispiel:
Zum Beispiel:
%Vor%Dieses Programm hat ein undefiniertes Verhalten. Auf meinem System stirbt es mit einem Segmentierungsfehler.
Das Problem tritt nicht in strchr
selbst auf. Es verspricht, die Zeichenfolge nicht zu ändern, die Sie an es übergeben, und es tut es nicht. Aber es gibt einen Zeiger zurück, den der Aufrufer dann verwenden kann, um ihn zu ändern.
Das ANSI C-Komitee, das in den späten 1980er Jahren konnte jede dieser Funktionen in zwei Versionen aufgeteilt hat, eine, die auf const
-Zeichenarrays und eine andere für nicht const
-Arrays wirkt:
Aber das hätte den vorhandenen Pre-ANSI-Code durchbrochen, der geschrieben wurde, bevor const
existierte. Dies ist der gleiche Grund, warum C String-Literale const
nicht erstellt hat.
C ++, das die meisten C-Standardbibliotheken erbt, behandelt dies, indem es überladene Versionen einiger Funktionen bereitstellt.
Die Quintessenz ist, dass Sie als C-Programmierer dafür verantwortlich sind, Objekte, die Sie als const
definiert haben, nicht zu ändern. In den meisten Fällen hilft Ihnen die Sprache, dies durchzusetzen, aber nicht immer.
Wie es diesen Funktionen gelingt, einen const
-Zeiger auf const
-Daten zurückzugeben, verwenden sie wahrscheinlich nur intern eine Umwandlung (nicht const_cast
, die nur in C ++ existiert). Dies setzt voraus, dass sie in C implementiert sind, was wahrscheinlich aber nicht erforderlich ist.
Wahrscheinlich wird nur Casting verwendet.
Es gibt zahlreiche Funktionen, die dieselbe Eigenschaft in der Standardbibliothek haben. Sicherheitsaspekte gegenüber der Einfachheit sind wahrscheinlich der Grund, da Sie Funktionen nicht wie in C ++ überladen können.
Sie erwarten, dass der Programmierer die Verantwortung übernimmt und endptr
nicht bearbeitet, wenn str
beispielsweise ein String-Literal ist.
C ist mit seinem begrenzten Typsystem eine praktische Sprache für praktische Leute.
strtol
macht eine const_cast
(oder gleichwertig). Das Umwandeln von const
away ist kein Problem, da der resultierende Zeiger den ursprünglichen const
-Inhalt ändern kann.
Aber strtol
gibt diesen Zeiger nur an Sie zurück, ohne ihn zu manipulieren, also ist alles in Ordnung.
Wie implementieren Sie strtol unter const-correctness?
Wenn Sie C11 _Generic
verwenden, kann Code entweder
Eine Implementierung wie unten wäre identisch, da nur die Erhaltung der Funktionssignatur benötigt wird. Da dies von strtol()
abweicht, sollte es etwas anderes genannt werden, zB strtol_s()
.
Was ist verloren: strtol_s()
ist keine wahre Funktion, daher kann kein Zeiger darauf gemacht werden.
Wie schafft er es, diesen in einen nicht-konstanten Zeiger auf das erste unverarbeitete Zeichen zu verwandeln, ohne zu schummeln?
strtol()
, obwohl es ein char **endptr
als zweites Argument benötigt, ändert% c_de% nicht.
Tags und Links c