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
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*
.
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.
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.
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.)
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
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.