String Zeiger und Array von Zeichen in c

8

Ich fange gerade an, C zu lernen, und habe etwas Verwirrung über den String-Zeiger und die Zeichenkette gefunden. Kann mir jemand helfen, meinen Kopf ein bisschen zu räumen?

%Vor%

also nehme ich an, dass sowohl name als auch name2 auf die Adresse ihres eigenen ersten Buchstabens zeigen. dann ist meine Verwirrung (siehe Code unten)

%Vor%

Ich erstelle einen Char-Zeiger namens Name2 und Name2 Zeiger auf den ersten Buchstaben von "Apple", das ist in Ordnung, dann erstelle ich ein anderes Array von Char und 10 Speicherplatz im Speicher zuordnen. und dann versuche name4 zu verwenden, was eine Adresse ist, die auf den ersten Buchstaben von "Apple" zeigt. Als Ergebnis habe ich einen Kompilierfehler bekommen.

Ich bin so frustriert von dieser Programmiersprache. manchmal funktionieren sie genauso. aber manchmal nicht. Kann jemand den Grund erklären und wenn ich wirklich eine Zeichenkette oder ein Array von Zeichen in getrennten Linien erstellen möchte. wie kann ich das machen?

Vielen Dank ...

    
eded 13.06.2013, 00:24
quelle

5 Antworten

6

Sie können ein Array initialisieren, wenn Sie es wie folgt deklarieren:

%Vor%

Da wir Char-Arrays jedoch typischerweise als Strings behandeln, erlaubt C einen Sonderfall:

%Vor%

Sobald Sie jedoch ein Array deklariert haben, können Sie es nicht neu zuweisen. Warum? Betrachten Sie eine Aufgabe wie

%Vor%

Die erste Zeile deklariert einen Zeichenzeiger und "zielt" auf den ersten Buchstaben in foo . Da foo eine String-Konstante ist, befindet sie sich irgendwo im Speicher mit allen anderen Konstanten. Wenn Sie den Zeiger neu zuweisen, weisen Sie ihm einen neuen Wert zu: die Adresse von bar . Die ursprüngliche Zeichenfolge foo bleibt jedoch unverändert. Sie haben den Zeiger verschoben, aber die Daten nicht geändert.

Wenn Sie jedoch ein Array deklarieren, deklarieren Sie überhaupt keinen Zeiger. Du reservierst eine bestimmte Menge an Speicher und gibst ihm einen Namen. Also die Zeile

%Vor%

beginnt mit der String-Konstante data , weist dann 5 neue Bytes zu, ruft sie c auf und kopiert die Zeichenfolge in sie. Sie können auf Elemente des Arrays genau so zugreifen, als hätten Sie einen Zeiger auf sie angegeben; Arrays und Zeiger sind auf diese Weise (für die meisten Zwecke) austauschbar.

Aber da Arrays keine Zeiger sind, können Sie sie nicht neu zuweisen.

Sie können c "point" nirgendwo anders machen, weil es kein Zeiger ist; Es ist der Name eines Speicherbereichs.

Sie können den Wert der Zeichenfolge ändern, entweder ein Zeichen gleichzeitig, oder indem Sie eine Funktion wie strcpy() :

aufrufen %Vor%

Effizienztipp

Beachten Sie auch, dass bei der Initialisierung eines Arrays im Allgemeinen eine Kopie der Daten erstellt wird: Der ursprüngliche String wird vom konstanten Bereich in den Datenbereich kopiert, wo er von Ihrem Programm geändert werden kann. Das bedeutet natürlich, dass Sie doppelt so viel Speicher verwenden, wie Sie vielleicht erwartet haben. Sie können die Kopie vermeiden und generell Speicher sparen, indem Sie stattdessen einen Zeiger deklarieren. Dadurch bleibt die Zeichenfolge im konstanten Bereich und es wird nur genügend Speicher für einen Zeiger zugewiesen, unabhängig von der Länge der Zeichenfolge.

    
Adam Liss 13.06.2013, 00:45
quelle
2

Obwohl Zeiger und Array bekannt vorkommen, sind sie unterschiedlich. Das char *name3 ist nur ein Zeiger auf char , es benötigt nicht mehr Speicher als ein Zeiger. es speichert nur eine Adresse, so dass Sie ihm eine Zeichenfolge zuweisen können, dann ändert sich die in name3 gespeicherte Adresse in die Adresse von "Apple" .

Aber Ihr name4 ist ein Array von char[10] , es enthält den Speicher von 10 Zeichen, wenn Sie es zuweisen möchten, müssen Sie strcpy oder etwas verwenden, um seinen Speicher zu schreiben, aber nicht mit ihm eine Adresse wie "Apple" .

    
leonhart 13.06.2013 00:33
quelle
2

Sie können einen Wert nicht direkt einem Array-Typ zuweisen (z. B. Ihr Array mit zehn char s name4 ). Für den Compiler ist name4 ein "Array" und Sie können den Operator = nicht verwenden, um mit einem String-Literal in ein Array zu schreiben.

Um den Inhalt der Zeichenfolge "Apple" tatsächlich in das zugewiesene Zehn-Byte-Array zu verschieben ( name4 ), müssen Sie strcpy() oder etwas von dieser Art verwenden.

Was Sie mit name3 machen, ist ziemlich anders. Es wird als char * erstellt und auf Müll oder Null initialisiert (an dieser Stelle ist das nicht sicher bekannt). Dann ordnen Sie ihm die Position der statischen Zeichenfolge "Apple" zu. Dies ist eine Zeichenfolge, die im schreibgeschützten Speicher vorhanden ist, und der Versuch, in den Speicher zu schreiben, auf den der Zeiger name3 zeigt, kann niemals erfolgreich sein.

Basierend darauf können Sie vermuten, dass die letzte Anweisung versucht, den Speicherplatz einer statischen Zeichenkette einer anderen Stelle zuzuordnen, die eine Sammlung von 10 char s darstellt. Die Sprache bietet Ihnen keine vordefinierte Möglichkeit, diese Aufgabe auszuführen.

Hier liegt seine Kraft.

    
Steven Lu 13.06.2013 00:31
quelle
2

Wenn Sie sagen

%Vor%

Sie deklarieren name3 , um auf die statische Zeichenkette "Apple" zu verweisen. Wenn Sie mit höheren Sprachen vertraut sind, können Sie sich das als unveränderlich vorstellen (ich werde es in diesem Zusammenhang erklären, weil es so klingt, als ob Sie es vorher programmiert hätten; für die technische Begründung überprüfen Sie den C-Standard).

Wenn Sie sagen

%Vor%

Sie erhalten einen Fehler, weil Sie zuerst ein Array von 10 Zeichen deklarieren (mit anderen Worten, Sie zeigen auf den Anfang eines 10-Byte-Abschnitts von veränderbarem Speicher) und versuchen dann Weisen Sie diesem Array den unveränderlichen Wert "Apple" zu. Im letzteren Fall erfolgt die eigentliche Datenzuweisung in einem schreibgeschützten Speichersegment.

Dies bedeutet, dass die Typen nicht übereinstimmen:

%Vor%

Wenn name4 den Wert "Apple" haben soll, verwenden Sie strcpy :

%Vor%

Wenn name4 den Anfangswert "Apple" haben soll, können Sie das auch tun:

%Vor%

Der Grund dafür ist, dass Ihr vorheriges Beispiel nicht funktioniert, weil "Apple" ein gültiger Arrayinitialisierer für char[] ist. Mit anderen Worten, Sie erstellen ein 10-Byte-Char-Array und setzen den Anfangswert auf "Apple" (mit 0s an den verbleibenden Stellen).

Dies kann sinnvoller sein, wenn Sie an ein int-Array denken:

%Vor%

Wahrscheinlich die einfachste umgangssprachliche Erklärung, die ich mir vorstellen kann, ist, dass ein Array eine Sammlung von Buckets für Dinge ist, während die statische Zeichenkette "Apple" eine einzelne Sache 'drüben' ist.

strcpy(name4, "Apple") funktioniert, weil es jedes der Dinge (Zeichen) in "Apple" in name4 eins nach dem anderen kopiert.

Es macht jedoch keinen Sinn zu sagen, "diese Sammlung von Eimern ist gleich diesem Ding dort drüben". Es macht nur Sinn, die Buckets mit Werten zu füllen.

    
sapi 13.06.2013 00:32
quelle
0

Ich denke, das wird helfen, es auch zu klären:

%Vor%

Ausgabe:

%Vor%

Wir sehen also arr == &arr . Da es ein Array ist, weiß der Compiler, dass Sie immer die Adresse des ersten Bytes haben wollen, egal wie es verwendet wird.

arr ist ein Array von 7 + 1 Bytes, die sich auf dem Stack von main() befinden. Der Compiler erzeugt Anweisungen, um diese Bytes zu reservieren, und füllt sie dann mit "Auf Wiedersehen". Es gibt keinen Zeiger!

ptr andererseits ist ein Zeiger, eine 4-Byte-Ganzzahl, ebenfalls auf dem Stapel. Deshalb ist &ptr sehr nahe an &arr . Aber was es zeigt ist eine statische Zeichenfolge ("Hello"), die im schreibgeschützten Bereich der ausführbaren Datei deaktiviert ist (daher ist ptr eine sehr unterschiedliche Zahl ).

    
Jonathon Reinhart 13.06.2013 00:39
quelle

Tags und Links