2012-08-31 15 views
9

Ich bin verwirrt über die folgende Codezeile:Array von Zeigern Arrays verkohlen

char* words[] = { "aaa", "bbbb", "ccccc", "dddddd" }; 

So wie ich das verstehe, wird jedes Wort zuerst gespeichert und dann jede Position des Arrays words wird zeigen Sie dann auf den ersten Charakter jedes Wortes. Wie werden diese Strings gespeichert? Gibt es hier eine dynamische Zuweisung oder werden diese Wörter auf dem Stack gespeichert?

Wenn sie auf dem Stapel gespeichert sind, auf welche Weise werden sie gespeichert? wenn ich einige der Inhalte words wie unten Zum Beispiel drucken:

#include <stdio.h> 
int main() { 
    char* words[] = { "aaa", "bbbb", "ccccc", "dddddd" }; 
    printf("\n\n(*words)[0] = %s", words[0]); 
    printf("\n\n(*words)[0]+1 = %s", words[0]+1); 
    return 0; 
} 

statt Druck aaa und bbbb, was ich bekommen ist aaa und aa. Ich verstehe nicht wirklich, was der Grund dafür ist, da die Art, wie ich es sehe, words[0]+1 auf die Zeichenfolge bbbb und nicht auf das zweite Zeichen von aaa zeigen sollte. Was geht hier vor sich?

+0

Sie sind verwirrend 'Worte gedruckt werden [0] + 1 ',' (Wörter + 1) [0] 'und' Worte [1] '? –

+0

Versuchen Sie '& words [0] + 1' – oldrinb

Antwort

2

die Art, wie ich es sehe, Worte [0] +1 auf den String bbbb zeigen sollten und nicht auf das zweite Zeichen von aaa

Nr words[0] ein char Zeiger selbst ist - es ist völlig in Ordnung, dass du das zweite Zeichen von "aaa" bekommst, indem du eins hinzufügst. Was Sie wollen, ist words + 1 oder &words[0] + 1, die korrekt "bbbb" sein wird.

Auch die Strings selbst werden nach dem Start der ausführbaren Datei zugewiesen und sie werden wahrscheinlich in den Daten oder BSS-Abschnitt der Binärdatei durch den Linker gesetzt. Wenn Sie außerdem words deklarieren und initialisieren, wird es auf dem Stapel wie jedes andere automatische Array zugewiesen und seine Elemente werden den Zeigern am Anfang jeder String-Konstante zugewiesen.

+0

Ich sehe. Ich habe versucht, Dinge wie 'words [1] [1] = 'u'' zu machen, um' bbbb' in 'bubb' zu ändern, aber' bbbb' bleibt gleich, nachdem ich es geändert habe (!). Ist dies dann, weil die Strings nur gelesen werden (ich nehme an, sie sind, da sie rvalues ​​sind)? –

+0

@curvature ja, das sind sie. Sei froh, dass es nicht abgestürzt ist - das Ändern von String-Konstanten ist UB. –

3

Wörter [0] zeigt auf das erste "a" in "aaa".

words [0] +1 verschiebt diesen Zeiger um ein Zeichen, so dass er auf das zweite "a" zeigt.

Worte [1] zeigt auf "bbbb"

Worte [1] +1 Punkte "bbb", z.B. das zweite "b" in "bbbb".

0

worte [0] gibt die Adresse von aaa zurück. Durch Hinzufügen von 1 wird die Adresse so erhöht, dass sie auf die zweite a zeigt.

Wollen Sie Wörter [0 + 1] haben?

Das sollte Ihnen geben, was Sie erwarten.

0
char* words[] = { "aaa", "bbbb", "ccccc", "dddddd" }; 

Alle 4 Strings haben eine statische Speicherdauer und werden vor dem Programmstart zugewiesen.

Im Initialisierer werden die Arrays in Zeiger auf char konvertiert und das Array words wird mit den Zeigerwerten initialisiert.

1

Die literalen Zeichenfolgen werden im statischen Speicher gespeichert. Ihr tatsächlicher Speicherort ist implementierungsabhängig, aber Literalzeichenfolgen werden irgendwo gespeichert, normalerweise im Datenteil der ausführbaren Datei - dies ist weder dynamisch noch Stapelzuweisung. Ihr Array enthält dann Zeiger auf diese Orte.

words [0] +1 sollte auf die Zeichenfolge bbbb und nicht auf das zweite Zeichen von aaa zeigen.

Dies ist einfach nicht wie Arrayindexierung funktioniert. Sie indexieren das Array von Strings mit words[0], jetzt haben Sie eine Zeichenfolge, und alle Operationen gelten für diese Zeichenfolge. Sie können Arithmetik mit Array-Indizes außerhalb des Index nicht ausführen. Um zu der Zeichenfolge "bbbb" zu gelangen, verwenden Sie words[1].

6

Der Unterschied ist, weil words[0]+1 nicht das gleiche wie words[0+1] ist.

Ersterer verweist auf das zweite Zeichen in words[0], während letzteres auf das zweite Wort zeigt.

1

Sowohl Stack- als auch Heap-Speicherbereich werden dynamisch zugewiesen - dh sie werden zur Laufzeit zugeordnet. Ist Ihr kompilierter Code dynamisch auf dem Heap oder Stack zugeordnet? Offensichtlich auch nicht. Der Speicher für Konstanten ähnelt dem Speicher für Code ... Sie werden in der ausführbaren Datei auf dem Datenträger gespeichert und in den Nur-Lese-Speicher geladen. (Anmerkung für Pedanten: Dies ist, wie Dinge in einer typischen Implementierung getan werden; es ist nicht durch den Sprachstandard vorgeschrieben.)

words[0] ist die Adresse des ersten 'a' von "aaaa". Hinzufügen von 1 zu dieser Adresse sollte sicherlich die Adresse des zweiten "a" von "aaaa" ergeben. Die Adresse von "bbbb" ist weit über words[1].

Im Format Ihres printf haben Sie "(* Wörter) [0]", aber das ist anders. *words ist das gleiche wie words[0]. (*words)[0] ist das gleiche wie **words, welches das erste "a" (nicht seine Adresse) von "aaaa" ist. Sie würden (*words)[0] mit %c, nicht %s drucken.

15

das ist wie ..

enter image description here

seit Worten ein Array von Zeichen von Zeigern, so dass jedes Array-Index von Wörtern wird die Adresse des Stringliteral, das heißt halten. Basisadresse der Stringliterale wenn Sie

printf("%s",words[0])// index 0 will print aaa.