2010-10-29 4 views
9

Erzielen diese beiden Codezeilen das gleiche Ergebnis? Wenn ich diese Zeilen in einer Funktion hatte, ist die Zeichenfolge in beiden Fällen auf dem Stapel gespeichert? Gibt es einen guten Grund, warum ich einen über den anderen verwenden sollte, abgesehen davon, dass ich den Nullabschluss in der ersten Codezeile nicht deklarieren muss?In C, kann ich eine Zeichenfolge in einer Zeigerdeklaration auf die gleiche Weise initialisieren, wie ich eine Zeichenfolge in einer char-Array-Deklaration initialisieren kann?

char s[] = "string"; 
char* s = "string\0"; 
+7

Nur zur Information, Sie brauchen das \ 0 im zweiten Beispiel nicht. Bei doppelten Anführungszeichen wird immer \ 0 in das Array eingefügt. – RMAAlmeida

+0

Und nur für das Vokabular, worüber Sie sprechen, sind keine Zuweisungen, sondern Deklarationen mit Initialisierern. Sie gehorchen verschiedenen Regeln. E.g Ihre erste Anweisung wäre nicht als Zuweisung erlaubt, Sie können keine Arrays zuweisen. –

+0

mögliche Duplikate von [C: Unterschiede zwischen Zeiger und Array] (http://stackoverflow.com/questions/1335786/c-differences-between-pointer-and-array) –

Antwort

23

Nein, diese beiden Zeilen erzielen nicht das gleiche Ergebnis.

char s[] = "string" ergibt ein modifizierbares Array von 7 Bytes, das anfänglich mit dem Inhalt 's' 't' 'r' 'i' 'n' 'g' '\0' gefüllt ist (alles wird zur Laufzeit aus dem String-Literal kopiert).

char *s = "string" Ergebnisse in einem Zeiger auf einige schreibgeschützt Speicher mit dem Zeichenfolge-Literal "Zeichenfolge".

Wenn Sie den Inhalt Ihrer Zeichenfolge ändern möchten, ist die erste die einzige Möglichkeit. Wenn Sie nur Lesezugriff auf eine Zeichenfolge benötigen, ist die zweite Zeichenfolge etwas schneller, da die Zeichenfolge nicht kopiert werden muss.


In beiden Fällen ist es nicht erforderlich, im Zeichenfolgenliteral einen Nullabschluss anzugeben. Der Compiler kümmert sich um das für Sie, wenn es die Schließung trifft“

+5

Auch die zweite ist nur für schreckliche Vermächtnis erlaubt Gründe dafür. Sie sollten 'const char * s =" string "verwenden;' –

+0

@Steve: Für C++ würde ich Ihnen vollkommen zustimmen. Für C tendiere ich dazu, ein bisschen mehr Spielraum zu geben, weil es in der Praxis zu viele Möglichkeiten gibt, dass dir das 'const' in die Quere kommt. (Das ist auch bekannt als Const-Vergiftung) –

+2

Wenn ich dodgy Bibliotheken verwende, stimme ich Ihnen (manchmal). Wenn der Code unter meiner Kontrolle steht, repariere ich ihn so, dass "const" mir nicht in die Quere kommt. Die Alternative besteht darin, Kopien von Zeichenfolgen zu erstellen, die als nicht konstante Parameter an fehlerhafte APIs übergeben werden müssen. Manchmal ist das machbar, wenn zum Beispiel die Zeichenfolge, die übergeben wird, ein Literal ist, das in der Nähe des Aufrufs definiert ist, oder als eine globale Zeichenfolge, dann verwenden Sie einfach die erste der beiden oben genannten Optionen. Andere Male ist es eine PITA, in diesem Fall können Sie entweder den Treffer von strdup nehmen oder "const" wegwerfen (was "unsicher" ist, aber dann verwenden Sie bereits eine "unsichere" API). –

2

Der Unterschied zwischen diesen beiden.

char a[] = "string"; 
char* b = "string"; 

ist, dass ein eigentlich ein statisches Array auf dem Stapel, während b ist ein Zeiger auf später auf dem Programmablauf eine konstante ist. Sie können den Inhalt eines ändern, aber b nicht.

1

Zusätzlich zu den anderen Antworten werde ich versuchen zu erklären, warum Sie die *s Variable nicht ändern können.

Konzeptionell, wenn ein Programm ist geladen in Speicher hat drei Bereiche (Segmente):

  • Codesegment: der Text des Programms hier gespeichert wird (es ist ein Nur-Lese-Bereich)
  • Datensegment: enthält alle globalen oder statischen Variablen, die eine haben vordefinierter Wert und kann geändert werden
  • Stack-Segment: Hier sind die Funktionen geladen, wie sie genannt werden. Die Menge von Werten (ein Stapelrahmen), die auf dem Stapel für jeden Funktionsaufruf gedrückt wird, der die Rückkehradresse von der Funktion und den lokalen Variablen enthält.

In Ihrem Fall das s[] Variable ist eine lokale Variable (array), in der main() Funktion, die mit dem Wert "string" initialisiert wird. Somit wird es auf dem Stapel gespeichert und kann modifiziert werden.

Die Variable *s ist ein Zeiger, der auf die Adresse "string\0" zeigt, eine Konstante, die sich im Codesegment befindet. Da es sich um einen schreibgeschützten Bereich handelt, können Sie dessen Inhalt nicht ändern.