C – warum ist strcpy() notwendig

Lesezeit: 5 Minuten

Kann mir bitte jemand erklären, warum strcpy() notwendig ist, um Zeichenfolgen Zeichen-Arrays zuzuweisen, wie im folgenden Code-Snippet.

int main(void) {

char s[4];

s = "abc"; //Fails
strcpy(s, "abc"); //Succeeds

return 0;
}

Was ist der Grund dafür s = "abc" scheitert? Und warum ist strcpy() die einzige Möglichkeit, Zeichenfolgen char-Arrays zuzuweisen, nachdem sie deklariert wurden? Es kommt mir merkwürdig vor, dass man eine Funktion nutzen muss, um eine Grundaufgabe zu erfüllen.

AnT steht mit Russlands Benutzer-Avatar
AnT steht zu Russland

Arrays in C sind nicht zuweisbar und nicht kopierinitialisierbar. Genauso sind Arrays in C. Historisch gesehen zerfallen Arrays im Wertkontext (auf der rechten Seite der Zuweisung) zu Zeigern, was formal die Zuweisung und Initialisierung von Kopien verhindert. Dies gilt für alle Arrays, nicht nur für char Arrays.

Die C-Sprache erbt dieses Array-Verhalten von ihren Vorgängern – B- und BCPL-Sprachen. In diesen Sprachen wurden Arrays durch physische Zeiger dargestellt. (Und offensichtlich ist die Neuzuweisung von Zeigern nicht das, was Sie möchten, wenn Sie ein Array einem anderen zuweisen.) In C-Sprache sind Arrays keine Zeiger, aber sie “simulieren” das historische Verhalten von B- und BCPL-Arrays, indem sie verfallen in den meisten Fällen auf Zeiger. Dieses historische Erbe ist es, was C-Arrays bis heute nicht kopierbar macht.

Eine Ausnahme davon ist die Initialisierung mit einem String-Literal. Dh du kannst

char c[] = "abc";

in diesem Fall sind wir konzeptionell Kopieren String-Literal "abc" zu ordnen c. Eine weitere Ausnahme ist ein in einen Strukturtyp eingeschlossenes Array, das kopiert wird, wenn das gesamte Strukturobjekt kopiert wird. Und das war es auch schon.

Dies bedeutet, dass Sie immer dann, wenn Sie ein nacktes (nicht umschlossenes) Array kopieren möchten, eine Speicherkopierfunktion auf Bibliotheksebene verwenden müssen, z memcpy. strcpy ist nur ein Geschmack davon, der speziell auf die Arbeit mit Saiten zugeschnitten ist.

  • Nur zur Verdeutlichung: Alle Array-Typen können mit einem geeigneten Initialisierer des Formulars initialisiert werden { val0, val1, ... }.

    – Jens Gustedt

    1. August 2011 um 21:29 Uhr

  • Du nicht haben um eine Bibliotheksfunktion zu verwenden; Sie können einzelne Zeichen zuweisen, z for (char *dst = s, *src = "abc"; *dst++ = *src++;) ;. Die Bibliotheksfunktion ist jedoch eine bessere Wahl, da sie einfacher zu lesen ist und möglicherweise für das System optimiert wird.

    – MM

    23. Januar 2015 um 21:01 Uhr


  • Ja, um mehr darüber zu sagen, was @AnT gesagt hat, strcpy() ist fast genau so memcpy()außer dass es das Nullbyte enthält.

    – RastaJedi

    18. April 2016 um 0:25 Uhr

Das ist einfach, was Arrays in C sind. Sie können ihnen nichts zuweisen. Sie können Zeiger verwenden, wenn Sie möchten:

char *p;
p = "abc";

Übrigens gibt es eine C-Häufig gestellte Fragen.

Arrays sind in C „Bürger zweiter Klasse“; ein Ergebnis dieses Vorurteils ist das Sie können ihnen nicht zuordnen.

  • Ja, ich verwende Zeiger, ich verstehe nur nicht, warum s = “abc” in meinem Beispiel nicht funktioniert. s ist ein char-Array und “abc” auch …

    – C_p678

    1. August 2011 um 16:03 Uhr


  • @ C_p678 – nein, s ist ein char-Array, “abc” ist ein Zeiger auf eine konstante Zeichenfolge.

    – MByD

    1. August 2011 um 16:03 Uhr


  • @ MByD: Nicht ganz richtig. "abc" ist kein Zeiger. "abc" ein Array des Typs char[4]die in diesem Kontext zu einem Zeiger vom Typ zerfällt char *. Beachten Sie, dass der String in C nicht konstant ist. Es ist in Ordnung nicht modifizierbar, aber der Typ selbst enthält es nicht const Qualifikation.

    – AnT steht zu Russland

    1. August 2011 um 16:09 Uhr


  • @AndryT: Um noch wählerischer zu sein, sind “const” und “constant” zwei sehr unterschiedliche Dinge. “const” hätte wahrscheinlich “readonly” heißen sollen. Eine Konstante oder ein konstanter Ausdruck kann zur Kompilierzeit ausgewertet werden; Ein konstantes Objekt ist eines, das zur Laufzeit nicht geändert werden kann. In Betracht ziehen const int r = rand();.

    – Keith Thompson

    2. August 2011 um 3:03 Uhr

Benutzeravatar von Jeff Paquette
Jeff Paquette

Kurze Antwort: historische Gründe. C hatte nie einen eingebauten String-Typ. Erst als C++ auftauchte, entstand std::string, und selbst das kam bei den ersten Implementierungen nicht an

Lange Antwort: Der Typ von “abc” ist es nicht char[]sondern eher char *. strcpy ist ein Mechanismus, mit dem Sie die Daten kopieren können, auf die der Zeiger zeigt (in diesem Fall ist das ABC).

strcpy ist nicht die einzige Möglichkeit, ein Array zu initialisieren, aber es ist intelligent genug, um die abschließende 0 am Ende der Zeichenfolge zu erkennen und zu berücksichtigen. Könntest du auch verwenden memcpy um die Zeichenfolge hinein zu kopieren s aber das erfordert, dass Sie die Länge der zu kopierenden Daten übergeben und sicherstellen, dass die abschließende 0 (NULL) vorhanden ist s

  • Die Art von "abc" ist char[4].

    – Jens Gustedt

    1. August 2011 um 21:27 Uhr

  • Und strcpy ist keine Initialisierung, sondern eine Zuweisung. Zeichenarrays können wie alle anderen Arrays initialisiert werden, siehe Antwort von AndreyT.

    – Jens Gustedt

    1. August 2011 um 21:31 Uhr

Der C-Sprache fehlt jede praktische Syntax, um einen Zeiger auf ein String-Literal zusammen mit einer Angabe seiner Länge zu erhalten. Einige Sprachen, einschließlich vieler Pascal-Dialekte, stellen jeder Zeichenfolge ein Byte voran, das ihre Länge angibt. Dies funktioniert für viele Zwecke gut, begrenzt jedoch Zeichenfolgenliterale auf 255 Zeichen. Der Ansatz von C ermöglicht die Unterbringung von Zeichenfolgenliteralen beliebiger Länge, fügt jedoch unabhängig von der Länge nur ein einziges Byte Overhead hinzu.

Nullterminierte Strings sind anderen Formen für fast jeden Zweck unterlegen Sonstiges als String-Literale, aber Literale sind bei weitem die gebräuchlichste Form von Strings, mit denen viele Programme umgehen müssen, und daher ist es ein beträchtlicher Vorteil, wenn Bibliotheksfunktionen effektiv mit ihnen umgehen; Es wird dann einfacher, nullterminierte Zeichenfolgen in Fällen zu verwenden, in denen sie nicht ideal sind, als einen separaten Satz von Bibliotheksroutinen für andere Typen zu haben.

1387010cookie-checkC – warum ist strcpy() notwendig

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

Privacy policy