strtok - char-Array versus char-Zeiger [duplizieren]

9

Bei Verwendung der Funktion strtok führt die Verwendung von char * anstelle von char [] zu einem Segmentierungsfehler.

Das läuft richtig:

%Vor%

Dies verursacht einen Segmentierungsfehler:

%Vor%

Kann jemand erklären, was diesen Unterschied im Verhalten verursacht?

    
Derek H 03.11.2010, 18:39
quelle

6 Antworten

25
%Vor%

Diese Zeile initialisiert string als groß genug Zeichen (in diesem Fall char[12] ). Es kopiert diese Zeichen in Ihr lokales Array, als ob Sie es ausgeschrieben hätten

%Vor%

Die andere Zeile:

%Vor%

initialisiert ein lokales Array nicht, es initialisiert nur einen lokalen Zeiger. Der Compiler darf es auf einen Zeiger auf ein Array setzen, das nicht geändert werden darf , als wäre der Code

%Vor%

Der Grund, warum C dies ohne einen Cast zulässt, liegt hauptsächlich darin, alten Code weiter kompilieren zu lassen. Sie sollten so tun, als wäre der Typ eines String-Literals in Ihrem Quellcode const char[] , das in const char* konvertiert werden kann, aber niemals in ein char* .

    
aschepler 03.11.2010, 18:48
quelle
11

Im zweiten Beispiel:

%Vor%

Der Zeiger string zeigt auf ein Zeichenfolgenliteral, das nicht geändert werden kann (wie strtok() gerne tun würde).

Sie könnten etwas nach folgendem Schema tun:

%Vor%

, damit string auf eine veränderbare Kopie des Literals zeigt.

    
Michael Burr 03.11.2010 18:43
quelle
4

strtok ändert die Zeichenfolge, die Sie übergeben (oder versucht, trotzdem). In Ihrem ersten Code übergeben Sie die Adresse eines Arrays, das auf einen bestimmten Wert initialisiert wurde. Da es sich jedoch um ein normales Array von Zeichen handelt, ist es erlaubt, es zu ändern.

Im zweiten Code übergeben Sie die Adresse eines Zeichenfolgenliterals. Der Versuch, ein Zeichenfolgenliteral zu ändern, führt zu undefiniertem Verhalten.

    
Jerry Coffin 03.11.2010 18:45
quelle
3

Im zweiten Fall ( char * ) befindet sich die Zeichenfolge im Nur-Lese-Speicher. Der korrekte -Typ von Zeichenfolgenkonstanten ist const char * . Wenn Sie diesen Typ zum Deklarieren der Variablen verwendet haben, werden Sie vom Compiler gewarnt, wenn Sie versuchen, ihn zu ändern. Aus historischen Gründen können Sie String-Konstanten verwenden, um Variablen vom Typ char * zu initialisieren, obwohl sie nicht geändert werden können. (Bei einigen Compilern können Sie diese historische Lizenz deaktivieren, z. B. mit dem -Wwrite-strings von gcc.)

    
zwol 03.11.2010 18:43
quelle
0

Der erste Fall erzeugt ein (nicht konstantes) char-Array, das groß genug ist, um den String aufzunehmen und ihn mit dem Inhalt des Strings zu initialisieren. Der zweite Fall erstellt einen Zeichenzeiger und initialisiert ihn so, dass er auf das Zeichenfolgenliteral zeigt, das wahrscheinlich im Nur-Lese-Speicher gespeichert ist.

Da strtok den Speicher ändern möchte, auf den das übergebene Argument verweist, verursacht der letztere Fall undefiniertes Verhalten (Sie übergeben einen Zeiger, der auf ein (const) Zeichenfolgenliteral zeigt), so dass es nicht stört

    
Chris Dodd 03.11.2010 18:43
quelle
0

Weil der zweite einen Zeiger (der sich ändern kann) zu einem konstanten String deklariert ...

Je nach Compiler / Plattform / OS / Speicherabbild ... wird die Zeichenfolge "Hallo Welt" als Konstante gespeichert (in einem eingebetteten System kann sie im ROM gespeichert werden) und wird versuchen, sie zu ändern dieser Fehler.

    
Matthieu 03.11.2010 18:44
quelle

Tags und Links