2015-04-23 5 views
25

Die Standardfunktion strstr wird verwendet, um die Position einer Teilzeichenfolge in einer Zeichenfolge zu finden. Beide Argumente der Funktion sind vom Typ const char *, aber der Rückgabetyp lautet char *.Wie strstr return ist keine Konstante

Ich würde gerne wissen, wie eine Standardfunktion implementiert wird, die die const-Korrektheit verletzt.

+5

Sie enthalten Cstring und nicht String.h? Ansonsten verwenden Sie C-Versionen - Gott weiß, was sie tun. Die C++ 'std :: strstr 'Versionen geben nur' char * 'zurück, wenn der erste Parameter auch ein Nicht-' const' 'char *' ist. Siehe [hier] (http://en.cppreference.com/w/cpp/string/byte/strstr). (Entschuldigung - habe gerade das C-Tag bemerkt ... welche Sprache benutzt du eigentlich?) –

+3

@TonyD Die C-Version ist 'char * strstr (const char *, const char *); ' –

+3

Beachten Sie, dass es in C++ zwei Überladungen von strstr gibt (http://www.cplusplus.com/reference/cstring/strstr/) eine mit const char * -Parameter und eine mit normalem char * und die Rückgabewerte Folgen. –

Antwort

13

C ermöglicht mit const oder nicht konstanten Zeiger auf Speicher zeigt, unabhängig davon, ob das Objekt mit dem const Qualifier oder nicht definiert wurde.

6,5 Expressions

  1. Ein Objekt hat seinen gespeicherten Wert nur durch einen L-Wert Ausdruck zugegriffen hat, die folgenden Typen einen hat:

- eine qualifizierte Version eines Typs, der mit dem effektiven Objekttyp kompatibel ist,

Der Prototyp von strstr in C ist:

char *strstr(const char *s1, const char *s2); 

Der zurückgegebene Zeiger zeigt, falls gültig, auf die Zeichenfolge s1. Dies kann mit einem Cast erreicht werden:

const char safe = 's' ; 
char* careful = (char*)&safe ; 

Das Problem besteht darin, diesen Speicher zu ändern.

6.7.3 Typ-Qualifikation

  1. Wenn versucht wird, mit einem const qualifizierten Typ, ein Objekt zu modifizieren durch einen L-Wert mit nicht konstantem Einsatz definiert -qualifizierter Typ, Das Verhalten ist nicht definiert.

Da Sie die Zeichenfolge erstellt, sollten Sie wissen, ob Sie es ändern können oder nicht, daher können Sie den Rückgabewert mit einem Zeiger auf const akzeptieren, um Probleme zu vermeiden:

const char* find = strstr(...) ; 
28

Alle const char * sagt Ihnen, dass strstr wird nicht die Zeichenfolge ändern, die Sie daran übergeben.

Ob Sie die zurückgegebene Zeichenfolge ändern oder nicht, liegt an Ihnen, wie es Ihre Zeichenfolge ist!

In C++ wurde dies durch Überladen der Methode geändert und mit zwei Versionen hat die const Eingangsversion einen const Ausgang.

In C ist das Sicherheitsniveau nicht ganz so hoch und Sie wissen selbst, ob Sie die zurückgegebene Zeichenfolge ändern sollten.

+3

Was C nicht hat, ist Funktion Überladung. Wenn die Funktion zuerst in C++ eingeführt wurde, könnte sie in zwei Varianten auftreten, const und non-const. Aber die Funktion wurde zuerst in C eingeführt. Außerdem wurde sie in K & R-Zeiten eingeführt, als es kein "const" -Schlüsselwort gab. – ach

13

Nach ISO C++ 21,8 (7) liefert ein strstrconst char* oder ein char* je nachdem, ob es ein oder ein const char*char* bekommt.

const char* strstr(const char* s1, const char* s2); 

char* strstr(char* s1, const char* s2); 
+3

Das stimmt für C++, aber in 'C99 gibt' strstr '' char * 'zurück. – Paul

+2

Ich sah zuerst das C++ - Tag, also verwendete ich den C++ - Standard. Sie haben Recht bezüglich des C-Standards. – NathanOliver

1

Der Rückgabewert ist nicht die Variable, die Sie als Parameter an die Funktion übergeben haben. Diese Funktion gibt einen Zeiger auf das erste Vorkommen im Heuhaufen einer der gesamten in nadel angegebenen Zeichenfolge zurück oder auf einen Nullzeiger, wenn die Folge im Heuhaufen nicht vorhanden ist.

+1

Es ist immer noch damit verbunden (Teil der gleichen Array-Deklaration oder Speicherzuweisung), und hat daher fast sicher die gleiche "richtige Const-Ness" wie Heuhaufen, wenn die Funktion richtig verwendet wird. – Random832

5

Es ist getan, indem Sie die Signatur angeben und die Implementierung den Compiler-Buildern überlassen.

Beachten Sie, dass die Rückgabe einer char*, die auf eine const char[] Zeichenfolge zeigt, nur gefährlich ist, aber noch keine Verletzung einer Regel. Jeder Versuch, in diesen Speicher zu schreiben, ist jedoch immer noch Undefined Behavior.

2

C++ provides two versions eine, die Konstanten und solche, die nicht-Konst.

const char* strstr(const char* str, const char* target);  
char* strstr(  char* str, const char* target); 

Da in C können wir nicht überlasten, werden wir mit zwei unangenehmen Entscheidungen links:

  • Entweder wir die Argumente als nicht-const nehmen, aber wenn unsere Quellen in der Tat const sind, dann müssen wir ausführen eine unangenehme Besetzung zu non-const.
  • Die zweite Option ist die, die wir haben, dass wir die Argumente als const annehmen, aber wir geben ein non-const zurück. Wir könnten ein const char * zurückgeben, aber dann könnten wir das Ergebnis niemals ändern.
4

Die strstr Funktion stammt aus einer Zeit zurück, bevor es so etwas wie ein Zeiger const war. In Fällen, in denen Code in den Speicher geschrieben werden könnte, der durch den ersten an strstr übergebenen Zeiger identifiziert wird, wäre es legal, dass Code in den vom zurückgegebenen Zeiger identifizierten Speicher schreibt, und in Fällen, in denen der zurückgegebene Wert nur verwendet würde Möglichkeiten, die mit einem Zeiger auf einen Nur-Lese-Speicher legal waren (zB ein String-Literal), könnte man einen solchen Zeiger legal an strstr übergeben.

Wenn heute eine ähnliche Funktionalität wie strstr definiert wurde, könnte sie mit zwei Methoden implementiert werden - eine davon könnte jeden Zeiger akzeptieren und einen Zeiger zurückgeben, der vom Empfänger nicht geschrieben werden konnte und nur einer davon Akzeptieren schreibbare Zeiger, würde aber einen Zeiger zurückgeben, den der Empfänger verwenden könnte, wie er es für richtig hält. Weil ein Code, der strstr verwendet, nur Lesezeiger übergeben müsste, und weil ein Code, der strstr verwendet, in der Lage wäre, in die Zeiger zu schreiben, die er liefern würde, wenn schreibbare Zeiger gegeben würden, war es notwendig, einen Satz von zu haben Zeigerqualifikationen funktionieren in beiden Richtungen. Die Konsequenz ist eine Reihe von Zeigerqualifikationen, die nicht wirklich "sicher" sind [da sie einen schreibbaren Zeiger auf einen schreibgeschützten Bereich des Speichers zurückgeben können] und der Code in einigen Fällen kompiliert, in denen er wirklich "nicht" sollte. aber das erlaubt Code, der vor den Tagen von const-Zeigern geschrieben wurde, weiter zu arbeiten, wie beabsichtigt.

Verwandte Themen