Ich fange an, C zu lernen, indem ich K & amp; R lese und einige der Übungen durchführe. Nach einigen Schwierigkeiten konnte ich die Übung 1-19 mit dem folgenden Code abschließen:
%Vor% Meine Frage bezieht sich auf das letzte Bit des Codes, in dem das Array tmp
char in s
kopiert wird. Warum funktioniert nicht einfach ein s = tmp;
? Warum muss man den Array-Index nach Index kopieren?
Vielleicht bin ich nur alt und mürrisch, aber die anderen Antworten, die ich gesehen habe, scheinen den Punkt völlig zu verfehlen.
C führt keine Array-Zuweisungen durch, Punkt. Im Gegensatz zu einigen anderen Sprachen (zB PL / 1; Pascal und viele seiner Nachkommen - Ada, Modula, Oberon usw.) kann man kein Array einem anderen Array durch eine einfache Zuweisung zuweisen. Auch hat C keinen String-Typ. Es hat nur Arrays von Zeichen, und Sie können Arrays von Zeichen (so wenig wie Sie Arrays eines anderen Typs kopieren können) nicht kopieren, ohne eine Schleife oder einen Funktionsaufruf zu verwenden. [String-Literale zählen nicht wirklich als String-Typ.]
Das einzige Mal, wenn Arrays kopiert werden, ist es, wenn das Array in eine Struktur eingebettet ist und Sie eine Strukturzuweisung vornehmen.
In meiner Ausgabe von K & amp; R 2nd Edition fragt Übung 1-19 nach einer Funktion reverse(s)
; in meiner Kopie von K & amp; R 1. Ausgabe war es Übung 1-17 statt 1-19, aber die gleiche Frage wurde gestellt.
Da Zeiger in dieser Phase noch nicht behandelt wurden, sollte die Lösung Indizes anstelle von Zeigern verwenden. Ich glaube, das führt zu:
%Vor% Kompilieren Sie dies mit -DTEST, um das Testprogramm einzuschließen und ohne nur die Funktion reverse()
definiert zu haben.
Mit der in der Frage angegebenen Funktionssignatur vermeiden Sie, pro Zeile der Eingabe strlen()
zweimal aufzurufen. Beachten Sie die Verwendung von fgets()
- selbst in Testprogrammen ist es eine schlechte Idee, gets()
zu verwenden. Der Nachteil von fgets()
im Vergleich zu gets()
besteht darin, dass fgets()
die nachlaufende neue Zeile, in der gets()
enthalten ist, nicht entfernt. Die Vorteile von fgets()
sind, dass Sie keine Array-Überläufe erhalten und Sie erkennen können, ob das Programm eine neue Zeile gefunden hat oder ob der Speicherplatz (oder die Daten) erschöpft war, bevor eine neue Zeile gefunden wurde.
Ihr tmp
-Array wurde auf stack deklariert, und wenn Ihre Methode fertig ist, wird der Speicher gehalten Die Werte werden aufgrund des Lösungsumfangs freigegeben.
s = tmp
bedeutet, dass s
auf den gleichen Speicherort wie tmp
zeigen sollte. Das heißt, wenn tmp
freigegeben ist, zeigt s
immer noch auf einen jetzt möglichen ungültigen, freigegebenen Speicherplatz.
Dieser Fehlertyp wird als fliegender Zeiger bezeichnet.
Bearbeiten: Dies ist kein veränderlicher Modifikator, wie in den Kommentaren dieser Antwort angegeben. Das Problem ist, dass s = tmp
nur ändert, worauf der Parameter verweist, nicht was das tatsächliche Array ist, das übergeben wurde.
Sie können auch mit einem einzigen Durchlauf rückwärts arbeiten, ohne ein ganzes Array im Speicher zu reservieren, indem Sie einfach die Werte nacheinander austauschen:
%Vor%Weil sowohl s als auch tmp Speicheradressen sind. Wenn Sie s = tmp, würden beide Zeiger auf das gleiche Array zeigen.
Angenommen, wir haben
%Vor%nach s = tmp hättest du
%Vor%Obwohl beide Arrays die gleichen Daten haben, wirkt sich eine Änderung von tmp auf beide aus, da beide Arrays tatsächlich gleich sind. Sie enthalten beide Daten, die sich in der gleichen Speicheradresse befinden. Wenn man also irgendeine Position des tmp-Arrays ändert oder das tmp-Array zerstört, wird s auf die gleiche Weise beeinflusst.
Indem Sie das Array durchlaufen, verschieben Sie einen Teil der Daten von einer Speicheradresse zu einer anderen.
In meiner Kopie von K & amp; R, Zeiger werden in Kapitel 4 erklärt. Ein kurzer Blick auf die ersten Seiten kann hilfreich sein.
Um die Diskussion hier abzurunden, gibt es noch zwei andere Möglichkeiten, als String umzukehren:
%Vor%Oder rekursiv:
%Vor%Versuchen Sie zu experimentieren und sehen Sie, was passiert, wenn Sie solche Dinge tun:
%Vor% Was passiert, wenn Sie das Array direkt in attemptModifyArray
ändern, überschreiben Sie gerade eine lokale Kopie der Adresse des Arrays x
. Wenn Sie zurückkehren, ist die ursprüngliche Adresse immer noch in main
's Kopie von x.
Wenn Sie die Werte im Array in modifyArrayValues
ändern, ändern Sie das eigentliche Array selbst, dessen Adresse in modifyArrayValues
lokale Kopie von x
gespeichert ist. Wenn Sie zurückkehren, behält x
immer noch das gleiche Array bei, aber Sie haben die Werte in diesem Array geändert.
In diesem Thread gibt es einen interessanten Unter-Thread über Arrays und Zeiger Ich fand diesen Link Wikipedia mit einer eigentümlichen Snippet-Code zeigt, wie ‚Plastilin‘ C sein kann!
%Vor%Was in C noch verwirrender ist, ist natürlich, dass ich das tun kann:
%Vor%Die Austauschbarkeit von Zeigern und Arrays scheint also in der C-Sprache so tief verankert zu sein, dass sie fast beabsichtigt ist Was denken alle anderen?
--- Original Beitrag ---
s und tmp sind beide Zeiger, also macht s = tmp einfach s auf die Adresse zeigen, wo tmp im Speicher lebt.
Ein weiteres Problem, mit dem, was skizzierte Sie ist, dass tmp eine lokale Variable ist, wird so ‚undefined‘ werden, wenn es den Bereich verlässt das heißt, wenn die Funktion zurückkehrt.
Stellen Sie sicher, dass Sie diese drei Konzepte gründlich verstehen, und Sie werden nicht sehr falsch gehen
Hoffe, das hilft und macht weiter!
Eine sehr direkte Antwort wäre - Sowohl s als auch tmp sind Zeiger auf einen Speicherort und nicht die Arrays selbst. Mit anderen Worten sind s und tmp Speicheradressen, in denen die Array-Werte gespeichert sind, aber nicht die Werte selbst. Eine der gebräuchlichsten Methoden, auf diese Array-Werte zuzugreifen, besteht in der Verwendung von Indizes wie s [0] oder tmp [0].
Wenn Sie jetzt versuchen, einfach zu kopieren, s = tmp, wird die Speicheradresse des tmp-Arrays in s kopiert. Das bedeutet, dass das ursprüngliche s-Array verloren geht und selbst der Speicherpointer auf das tmp-Array zeigt.
Sie werden diese Konzepte zu gegebener Zeit gut verstehen, also gehen Sie weiter durch das Buch. Ich hoffe, diese elementare Erklärung hilft.