Warum kann einem char*-Zeiger ein String zugewiesen werden, aber nicht einem char[] Reihe?

Lesezeit: 5 Minuten

Nicks Benutzeravatar
Nick

Kann jemand erklären, warum das mit dem Zeiger funktioniert:

char * str1;

str1 = "Hello1";

str1 = "new string";

// but not this
char str2 [] = "hello";
str2 = "four";

// or this
char str3 [];
str3 = "hello";
str3 = "hello";

  • Diese Frage betrifft denselben Grund, nur anders formuliert. Ich bin mir nicht sicher, ob dies doppelt genug ist, um es zu schließen, aber die Antworten dort treffen zu.

    – Tim Post

    24. Juli 2011 um 3:17 Uhr

  • @Tim Post: Die angebliche doppelte Frage und ihre Antwort haben meiner Meinung nach nichts mit dieser Frage zu tun, da diese zur Kompilierzeit, die andere zur Laufzeit fragt

    – Armen Tsirunyan

    24. Juli 2011 um 10:48 Uhr


Benutzeravatar von tryurbest
am besten

Warum es mit Zeigern funktioniert:

Wenn du sagst char * str1 In C weisen Sie einen Zeiger im Speicher zu. Wenn du schreibst str1 = "Hello";, erstellen Sie ein Zeichenfolgenliteral im Speicher und lassen den Zeiger darauf zeigen. Wenn Sie ein weiteres Zeichenfolgenliteral erstellen "new string" und zuordnen str1ändern Sie lediglich, wohin der Mauszeiger zeigt.

Warum es mit Arrays nicht funktioniert:

Wenn du sagst char str2 [] = "Hello", erstellen Sie ein Zeichenfolgenliteral und fügen es während seiner Definition in das Array ein. Es ist in Ordnung, keine Größe anzugeben, da das Array sie berechnet und a anhängt '\0' dazu. Sie können diesem Array nichts neu zuweisen, ohne die Größe zu ändern. Deswegen str2 = "four" wird nicht funktionieren.

Im Falle von str3, es ist der gleiche Fall. Sie haben die Größe des Arrays nicht in der Definition definiert, daher wurde seine Größe mit 0 berechnet. Sie können nichts Neues zuweisen, ohne die Größe des Arrays zu ändern.

  • Prost, TryUrBest. Die meisten C-Bücher, die ich mir angesehen habe, machen eine wirklich große Sache aus Strings, Zeigern und Arrays. Ist das im Fall von str1 (dem Zeiger) der richtige Weg? Hören Sie auf, sich Gedanken darüber zu machen, “mache ich es 100% richtig”, und machen Sie einfach Zeiger auf Zeichenfolgen und verwenden Sie sie wie oben beschrieben? Sie sagten, dass die erste Methode den Zeiger bewegt, ist die orig. Daten dann vernichtet, oder ist es ein Leak?

    – Nick

    24. Juli 2011 um 6:03 Uhr

  • @tryurbest: Darf ich noch eine Frage hinzufügen? Falls char* str=”some string” verwendet wird, wird diese Zeichenfolge als Zeichenfolge mit fester Größe betrachtet. Später wird dieser Zeiger verarbeitet, um weitere Zeichenfolgen hinzuzufügen. Wird das eine Speicherzugriffsverletzung erzeugen? Vielen Dank! Eigentlich habe ich es getestet und sehe den Fehler. Aber ich bin mir nicht sicher über den Teil “String mit fester Größe” oder “String mit konstanter Größe” dort drüben

    – TSL_

    29. November 2014 um 3:08 Uhr


  • Was passiert mit der alten Zeichenfolge “Hallo”. Ist dies ein Speicher und trägt er zum Speicherleck bei? Oder wird das automatisch freigegeben?

    – Jon Wheelock

    11. Oktober 2015 um 2:05 Uhr

  • Laut KN King ist in Ihrem zweiten Beispiel char str2 [] = “Hello”, obwohl “Hello” ein String-Literal zu sein scheint, ist es das nicht. Stattdessen betrachtet C es als Abkürzung für einen Array-Initialisierer.

    – Ilstam

    17. Juni 2017 um 19:24 Uhr

Ein Array und ein Zeiger sind verschiedene Dinge, deshalb. Sie können einem Zeiger zuweisen, aber nicht einem Array. Eine besondere Ausnahme wird für die Initialisierung von char-Arrays mit String-Literalen gemacht.

char a[] = "Hello"; //initialize a char array with string literal. Special case, OK
char* p = "Hello"; //initializa a pointer with an array(which gets converted to pointer)
p = "My";   //assign pointer to point to another value. OK
a = "My";   //error, arrays cannot be assigned to. Use `strcpy`

Zeichenfolgenliterale (z. B. „Hallo“) haben einen Typ char[N] wo N ist die Anzahl der Zeichen (einschließlich der abschließenden '\0'). Ein Array kann in einen Zeiger auf sein erstes Element umgewandelt werden, aber Arrays und Zeiger sind nicht dasselbe, was auch immer einige schlechte Bücher oder Lehrer sagen mögen.

  • Nicht vergessen const als Thema hier.

    – Welpe

    23. Juli 2011 um 21:28 Uhr

  • @DeadMG: AFAIK in C-String-Literalen sind es nicht const char [N]. Sie sind char [N]. Deshalb haben wir (früher) die implizite Konvertierung in char* von String-Literalen in C++. Liege ich falsch?

    – Armen Tsirunyan

    23. Juli 2011 um 21:30 Uhr


  • @Armen: Nein, das sind sie offiziell nicht const char[N], aber in Wirklichkeit sind sie es sehr oft. Die meisten Compiler legen Zeichenfolgenliterale im Nur-Lese-Speicher ab. Das bedeutet, dass der Benutzer dies im Allgemeinen nicht versuchen sollte *p = 'A';.

    – Rudy Velthuis

    23. Juli 2011 um 21:39 Uhr

  • @Rudy: Unabhängig davon, wo der Compiler ein String-Literal aufbewahrt, tut er das *p = 'A' hat ein undefiniertes Verhalten, das meiner Meinung nach für die Frage des OP irrelevant ist. Aber der Typ eines String-Literals ist (leider) gerecht char[N] in C.

    – Armen Tsirunyan

    23. Juli 2011 um 21:44 Uhr

  • OK Jungs, danke. Armen hat einen wirklich guten Punkt gemacht. Ich habe gelesen, dass Zeiger und Arrays im Grunde gleich sind.

    – Nick

    24. Juli 2011 um 5:50 Uhr

Einfach gesagt, weil ein Array kein erstklassiges Objekt in C/C++ ist. Die einzige Möglichkeit, einem Array zuzuweisen, ist die Verwendung von str(n)cpy oder memcpy.

Während ein Array zu einem Zeiger zusammenfällt, wenn es an eine Funktion übergeben wird, ist es nicht möglich, einem Array zuzuweisen, außer zur Kompilierzeit als Initialisierung.

Der Fall mit Zeigern
Es funktioniert, weil, wenn Sie wie zuweisen str1="Hello" , Sie erstellen tatsächlich ein Zeichenfolgenliteral mit dem Namen hallo, weisen es irgendwo im Speicher zu und weisen dem Zeiger die Adresse des ersten Zeichens des Literals zu. Da der Zeiger nicht konstant ist, können Sie ihm erneut andere Adressen zuweisen. Ein weiterer wichtiger Punkt ist, dass sich das erstellte Zeichenfolgenliteral im Nur-Lese-Speicher befindet.

Der Fall mit Zeichen-Array
Sie können ihm während der Initialisierung ein Zeichenfolgenliteral zuweisen, da dies von der Sprache unterstützt wird. Und verwechseln Sie Zuweisung nicht mit Initialisierung. Da es sich bei der Zuweisung um ein Zeichenarray handelt, müssen Sie den Wert Zeichen für Zeichen ändern. Sie versuchen, die erste Adresse des Zeichenfolgenliterals an das erste Zeichen des Arrays zu adressieren (der Name des Arrays gibt die Adresse des ersten Elements des zurück array).Und das ist eindeutig nicht richtig, da das erste Element kein Zeiger ist, es kann keine Adresse speichern.

Benutzeravatar von Sawan
Sawan

Es liegt einfach daran, wenn Sie diesen Code schreiben:

char str2 [] = "hello";

oder auch:

int arr[] = {1,2,4,4,5};

es erstellt str2 oder arr als ständiger Zeiger. Aus diesem Grund können Sie diesen Zeigern keine anderen Werte neu zuweisen, während Sie später einen normalen Zeiger erstellen und ihm alles zuweisen können.

1417050cookie-checkWarum kann einem char*-Zeiger ein String zugewiesen werden, aber nicht einem char[] Reihe?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy