Was sind die Besonderheiten der Definition eines Strings in C?

10

Ich soll eine Hausaufgabenfrage für eine meiner Klassen beantworten. Insbesondere soll ich sagen, ob bestimmte Arrays in C als Strings betrachtet werden oder nicht. Basierend auf diesem Artikel ( https://www.geeksforgeeks.org/strings-in-c-2/ ) weiß ich, dass Zeichenfolgen ein Array von Zeichen mit dem Nullterminator am Ende sind.

Mein Hauptproblem ist ein Teil der Frage, die nach einem Array fragt, das so aussieht:

char c1[] = { 'C', 'S', '\0', '3', '2', '4', '\0' };

Dies ist offensichtlich ein Array von Zeichen mit einem Null-Abschlusszeichen am Ende. Wird es jedoch immer noch als Zeichenfolge betrachtet, da es in der Mitte auch ein Null-Abschlusszeichen hat? Wie wirkt sich das auf die Zeichenfolge aus?

EDIT: Aufgrund von Kommentaren habe ich den tatsächlichen Wortlaut der Frage angegeben:

"Welche der folgenden Arrays können als" Zeichenfolgen "betrachtet werden, um sie als Argumente für strcpy (), strncpy (), strcmp (), strncmp () und ähnliche Zeichenfolgenfunktionen zu verwenden (geben Sie alle zutreffenden an)?"

EDIT: Ich habe meinem Professor eine E-Mail darüber geschickt, da die Frage nicht eindeutig formuliert zu sein schien (wie mehrere Leute betonten). Wenn jemand neugierig ist, sagte er zu mir: "Ja, es ist eine Zeichenfolge. Der Schlüssel ist, dass es ein Nullzeichen gibt. Aber das wirkt sich natürlich auf alle Zeichenfolgenoperationen aus. Die Zeichenfolge endet mit dem Nullzeichen."

Quango
quelle
4
Man könnte sagen, dass es sich um die Zeichenfolge handelt, an die "CS"einige Bytes Müll angehängt sind (in diesem Fall ist das letzte NUL-Zeichen irrelevant). Aber es ist keine Zeichenfolge "als Ganzes". - Wenn Sie dies jedoch strcpyusw. zuführen, wird Ihr PC nicht explodieren, da diese Funktionen nur den "CS"Teil "sehen" .
Hagen von Eitzen
2
c1 kann absolut als Argument für verwendet werden strcmp(). Ob es als Argument für die Mutation von Zeichenfolgenfunktionen verwendet werden kann, hängt von zusätzlichen Faktoren ab, die nicht angegeben werden.
EOF
2
Der Inhalt von c1ist veränderlich, daher verstehe ich nicht, warum es kein gültiges Zielargument für strcpyoder ähnliches sein würde, es sei denn, es war nicht groß genug, um die Quellzeichenfolge aufzunehmen. Das würde es nicht zu einer Saite machen, nur nicht zu einer für einen bestimmten Zweck geeigneten.
John Bollinger
1
Insgesamt stimme ich zu, dass die Frage nicht eindeutig formuliert ist. Der Ausdruck c1würde die grundlegenden Anforderungen für Zeichenfolgenargumente für alle (engen) Zeichenfolgenfunktionen der Standardbibliothek erfüllen, einschließlich aller speziell genannten, aber das Verhalten entspricht möglicherweise nicht den Erwartungen oder Wünschen des Aufrufers (selbst wenn undefinierte Verhaltensweisen ignoriert werden, die hervorgerufen werden könnten).
John Bollinger
1
Notiere dass der Typ nicht sein muss char. Jeder Zeichentyp reicht aus .
chux - Monica

Antworten:

8

c1ist meistens [1] äquivalent zu &c1[0], was eine Zeichenfolge enthält , "CS".

Es gibt eine zweite Zeichenfolge dort lauert, "324"am Start &c1[3]- aber solange Sie Zugriff auf c1wie c1die Zeichenfolge "CS"ist es, alle Funktionen strcpy()et al. würde sehen.


[1]: c1ist ein Array, &c1[0]ist ein Zeiger.

DevSolar
quelle
Ist es also richtig, c1als Zielzeichenfolge in einem strcpy()Befehl zu verwenden? Die Frage ist mehrdeutig - bestenfalls.
Andrew Henle
1
Natürlich können Sie c1als Argument für beide verwenden strcpy(). Es ist in jeder Hinsicht eine ganz normale Saite. Gewöhnliche Zeichenfolgen enthalten nach ihren Terminatoren häufig Restmüll. Die Tatsache, dass dieser Müll im Programm fest codiert ist, erweckt den Eindruck, dass der Autor beabsichtigt, ihn c1ohne Zeichenfolgen zu verwenden, aber das war nicht Teil der Frage.
Lee Daniel Crocker
" c1ist gleichbedeutend mit &c1[0]" irreführend. c1ist ein Array. &c1[0]ist ein Zeiger.
chux - Monica
2

Wenn Sie die Besonderheiten der Definition einer Zeichenfolge in C kennen möchten, gehen Sie zur Quelle.

Aus dem C90-Standard :

7 Bibliothek

7.1 Einführung

7.1.1 Definitionen von Begriffen
Eine Zeichenfolge ist eine zusammenhängende Folge von Zeichen, die mit dem ersten Nullzeichen abgeschlossen sind und dieses enthalten. Ein "Zeiger auf" eine Zeichenfolge ist ein Zeiger auf das ursprüngliche Zeichen (niedrigste Adresse). Die "Länge" einer Zeichenfolge ist die Anzahl der Zeichen vor dem Nullzeichen und ihr "Wert" ist die Reihenfolge der Werte der enthaltenen Zeichen in der angegebenen Reihenfolge.

(Es gab keine relevanten Änderungen in späteren Standards.)

Somit c1enthält zwei aufeinanderfolgende Strings „CS“ und „324“, ist aber nicht selbst ein String.

Wenn wir ein Array an eine Funktion übergeben, zerfällt es in einen Zeiger auf sein erstes Element und zeigt somit +c1auf eine Zeichenfolge (die erste), was für jede Funktion gut genug ist, die einen Zeiger auf eine Zeichenfolge erwartet. Es zeigt nicht auf eine Zeichenfolge "CS \ 0324", aber das ist wahrscheinlich gut genug für die Frage Ihrer Instruktoren, die nicht eindeutig ist.

Deduplikator
quelle
4
Ich würde argumentieren, dass selbst nach dieser Definition c1 eindeutig die Zeichenfolge "CS" ist. Zeitraum. Die Tatsache, dass es nach dem Terminator möglicherweise Bytes ungleich Null enthält, ist irrelevant - viele Zeichenfolgen werden in ihrem Leben so sein.
Lee Daniel Crocker
+c1zeigt auf eine Zeichenfolge, da c1mit einer Zeichenfolge beginnt. Das macht jedoch in keiner Weise, Form oder Gestalt c1einen String.
Deduplikator
2
Dies ist die Adresse eines Speicherabschnitts, der einige Zeichen enthält, die durch ein Null-Byte abgeschlossen sind. Wenn printf () mit% s in Ordnung wäre, würde es eine vollkommen gute Zahl geben, die an strlen () übergeben wird, würde funktionieren, wenn es an strcpy () übergeben wird usw. Klingt für mich wie eine Zeichenfolge.
Lee Daniel Crocker
Na sicher. Aber Arrays können durchaus Strings sein.
Lee Daniel Crocker
0

Als Ergänzung zu @ DevSolar's Antwort entdeckte ich etwas, nachdem ich mit der angegebenen Zeichenfolge herumgespielt hatte, wenn es so wäre:

char c1[] = { 'C', 'S', '\\0', '3', '2', '4', '\\0' };

Wenn Sie diese Zeichenfolge ausgeben, erhalten Sie CS03240und die Größe dieser Zeichenfolge ist 7. Nach meinem Verständnis \\0wird verwendet, um das Nullzeichen ( dh \0 ) zu bezeichnen. Wenn Sie tun:

printf("\0");

Sie sehen nichts im Ausgabeprotokoll, aber wenn Sie dies tun:

printf("\\0");

Sie sehen ein \0, etwas, das erwartet wird, weil Sie ein Sonderzeichen verwenden müssen, um Sonderzeichen wie Backslashes oder Anführungszeichen auszugeben \.

Was mich verwirrt, ist die Ausgabe CS03240und die Größe 7. Es ist allgemein bekannt, dass die Größe einer Zeichenfolge die Anzahl der darin enthaltenen Zeichen plus eins (für das Nullzeichen) ist. Auch die Größe beträgt 7, auch für die Zeichenfolge char c1[] = { 'C', 'S', '\0', '3', '2', '4', '\0' };.

Also vielleicht eine Antwort auf diese Frage, was ist hier los?

rasengan__
quelle
1
'\\0'ist kein Nullzeichen . Es ist eine Konstante mit mehreren Zeichen. Es hat einen implementierungsdefinierten Wert, der sicherlich außerhalb des Bereichs von liegt char. c1[]ist keine Zeichenfolge, da kein Nullzeichen vorhanden ist . "Sie geben diese Zeichenfolge aus" führt wahrscheinlich zu undefiniertem Verhalten .
chux - Monica
Ich habe dich nicht genau verstanden, obwohl ich Konstanten mit mehreren Zeichen nachgeschlagen habe. Wenn c1 [] keine Zeichenfolge ist, weil es am Ende kein Nullzeichen enthält, warum wird die Größe dann im Anfangsfall als 7 ausgegeben, wie vom OP angegeben?
rasengan__
char c1[] = { 'C', 'S', '\0', '3', '2', '4', '\0' };ist Größe 7, da es mit 7 Werten initialisiert wird. Die Größe hat nichts mit Strings zu tun . char c1[] = { 1, 2, 3, 4, 5, 6, 7 };würde es immer noch Größe 7 machen.
chux - Reinstate Monica
Wie enthält das Array c1einen Stich? Das ist ein separates Thema. Siehe auch
chux