Hatten Sie in Ihrem eigenen Studium (allein oder für eine Klasse) einen "ah ha" -Moment, in dem Sie die Hinweise wirklich verstanden haben? Haben Sie eine Erklärung, die Sie für Anfängerprogrammierer verwenden, die besonders effektiv zu sein scheint?
Wenn zum Beispiel Anfänger zum ersten Mal auf Zeiger in C stoßen, können sie einfach &
s und *
s hinzufügen, bis sie kompiliert sind (wie ich es selbst einmal getan habe). Vielleicht war es ein Bild oder ein wirklich gut motiviertes Beispiel, das Zeiger für Sie oder Ihren Schüler zum "Klicken" brachte. Was war es und was hast du versucht, bevor es nicht zu funktionieren schien? Waren Themenvoraussetzungen (z. B. Strukturen oder Arrays)?
Mit anderen Worten, was war notwendig, um die Bedeutung von &
s zu verstehen und *
wann Sie sie mit Zuversicht verwenden konnten? Das Erlernen der Syntax und Terminologie oder der Anwendungsfälle reicht nicht aus. Irgendwann muss die Idee verinnerlicht werden.
Update: Ich mag die Antworten so weit; Bitte lass sie kommen. Hier gibt es viele großartige Perspektiven, aber ich denke, viele sind gute Erklärungen / Slogans für uns, nachdem wir das Konzept verinnerlicht haben. Ich bin auf der Suche nach den detaillierten Zusammenhängen und Umständen, als es Ihnen dämmerte.
Zum Beispiel:
In C verstand ich Zeiger nur ein wenig syntaktisch. Ich hörte zwei meiner Freunde, die Zeiger einem anderen Freund erklärten, der fragte, warum a
struct
mit einem Zeiger übergeben wurde. Der erste Freund sprach darüber, wie es referenziert und modifiziert werden musste, aber es war nur ein kurzer Kommentar des anderen Freundes, bei dem es mir auffiel: "Es ist auch effizienter." Das Übergeben von 4 Bytes anstelle von 16 Bytes war die letzte konzeptionelle Verschiebung, die ich brauchte.
quelle
Antworten:
Memory-as-a-Grid-Diagramm
Normalerweise stelle ich das Gedächtnis als "Gitter" dar, so dass ich Adressen erfinden, verschiedene Speicherbereiche hervorheben und in die Zellenwerte (oder noch weiter in ihre binären Darstellungen) schreiben und die Zeiger im Gedächtnis mit den Werten verknüpfen kann, die sie haben zeigen auf. (Und dann noch erwähnen, dass es eine Vereinfachung ist).
Normalerweise ist es für die meisten meiner Schüler ein "ohhhh" Moment.
Symbol Jonglieren
Wenn sie dann aufhören, die Verwendung von & und * zu vergessen, ist es ganz einfach: Präsentieren Sie sie auf dieselbe Weise, wie sie mathematische oder physikalische Berechnungen durchführen. Wenn Sie eine Entfernung in km durch eine Zeit in Stunde teilen, erhalten Sie eine Geschwindigkeit in km / h. Was drin ist, muss draußen sein. Einfach.
printf zur Rettung
Nur ein paar grundlegende Beispiele zu machen, die visuell darstellen, was Sie mit diesen erklärt haben, wird sie in dem trösten, was sie zu verstehen glauben, oder ihnen die Gelegenheit geben, zu sagen, "ah, ich verstehe das nicht".
Seien Sie umfangreich
Behandeln Sie Zeiger für einfache Typen und stellen Sie sicher, dass sie den Unterschied zwischen der Adressierung und der Größe eines Datentyps verstehen, sowie Strukturen, Arrays und mehrere Ebenen.
Starten Sie dann die Zeigerarithmetik.
Anhang: Rekursion
Normalerweise erkläre ich Rekursionen auf ähnliche Weise anhand einer visuellen Darstellung. Lassen Sie sie das Alphabet mit einer vorgefertigten Funktion drucken, die ein einzelnes Zeichen schreibt, und bitten Sie sie dann, es in umgekehrter Reihenfolge zu drucken, indem Sie nur zwei Zeilen ändern.
Normalerweise gibt es ein "Was zum ...?" Moment, und wenn Sie Ihrem printf nur einen weiteren Parameter hinzufügen, um numerische Werte zu drucken und die Schritte einzurücken, wird dies zu einem erleichterten Seufzer.
Alternativen: Das Play-Doh-Modell und die Wasserbecher
Ich hatte tatsächlich einige Kollegen an einer Universität, die den Studenten ein Video zeigten, in dem Zeiger und Speicherzugriffe mit Play-Doh-Paste erklärt wurden. Es war unglaublich clever und gut gemacht, obwohl ich diese Technik selbst nie wirklich angewendet habe, außer bei sehr jungen Lernenden, die daran interessiert waren, Programmieren zu verstehen (aber normalerweise würde ich sie nicht zu früh mit Hilfe von Zeigern zu einer Sprache führen). Grundsätzlich werden winzige Bälle aus play-doh verwendet, die Sie an andere größere Bälle aus play-doh anhängen können, die Speicherbereiche darstellen, und die Sie kombinieren können, um sie entweder zu verknüpfen (wie in einer verknüpften Datenstruktur) oder zusammenzuführen (wie in einer zusammenhängenden Struktur) Speicherplatz). Das Verwenden verschiedener Farben für die Speicherbereiche, auf die verwiesen wird, und die Zeiger helfen ebenfalls. Aber ich denke immer noch, dass das Memory-as-a-Grid-Ding besser funktioniert, wie Sie deutlich zeigen können, handelt es sich bei dem Zeigen wirklich um "Adressieren", wie auf einer "Karte / einem Raster". Während der Play-Doh-Modus sie immer noch verwirrt zu denken, dass sich die Dinge im Gedächtnis wirklich berühren.
Die Sache mit dem Wasserbecher wurde auch direkt von einer Kollegin benutzt, aber ich weiß nicht, ob sie darauf gekommen ist. Es war ein interessanter Ansatz, aber ich bemerkte, dass viele Schüler von der Erklärung verwirrt waren. Etwas, das der DevSolo-Kaffeetassentechnik ähnelt . Aber ich denke, es ist tatsächlich irreführend, da Sie die Schüler dazu bringen, Container, Datenstrukturen, Zeiger und Arrays zu verwechseln. Ich nehme an, dass es ein interessanter Ansatz ist, Arrays am Anfang zu erklären, aber ich würde mich nicht lange daran halten.
quelle
Jemand viel weiser als ich einmal sagte:
quelle
Ich fand, dass Diagramme sehr hilfreich waren. Beispiel:
Diese Art von Diagramm hat mir gezeigt, dass Zeiger ihre eigene Variable sind, aber einen Wert enthalten, der die Position eines anderen Objekts, dh eines Arrays oder einer Zeichenfolge, darstellt. Wenn ich mit Bleistift fertig bin, kann ich mein Programm auch auf Papier oder auf einer Tafel / Whiteboard nachzeichnen.
quelle
Als ich zum ersten Mal etwas über Zeiger "lernte", stieß ich darauf. Meine Universität hatte die Entscheidung schon lange getroffen, bevor ich mich einschrieb, um den Lehrplan auf Java zu konzentrieren. Als mein Professor für Datenstrukturen eine Vorlesung über C hielt und uns aufforderte, eine XOR-Liste mit Hinweisen zu implementieren, hatte ich das Gefühl, etwas zu lernen weit über meinen Kopf.
Ich habe die Definition verstanden:
Trotzdem habe ich einen großen Teil des Konzepts nicht verstanden. Rückblickend denke ich, dass es um drei Dinge ging:
Was genau ist ein Speicherort? (Zu der Zeit habe ich keinen Computer Organization Kurs belegt)
Die umständliche Syntax (Also ähm ... warum genau ist es wie "int * ip" definiert, aber anschließend beziehe ich mich auf die Variable als "ip"?)
Wie genau ist es vorteilhaft, die Adresse einer Variablen zu speichern, anstatt nur die Variable zu verwenden?
Erst als ich das K & R-Buch kaufte und jedes Problem erledigte, bekam ich wirklich ein Gespür für Hinweise. Abgesehen von der Tatsache, dass ich den Computer Organization-Kurs schon lange abgeschlossen hatte (was meiner Meinung nach vor dem Erlernen von C erforderlich sein sollte), hing ein Teil davon mit der Tatsache zusammen, dass ich erkannte, dass Zeiger für Funktionen, Arrays, Strukturen ... verwendet werden können. nützliche Dinge zu tun und nicht nur als Speicher für Adressen von gewöhnlichen Variablen.
Aber mein "Aha" -Moment war bei weitem die Art und Weise, wie K & R die umständliche Syntax der Definition eines einfachen Zeigers erklärte. Ich habe im gesamten Buch Notizen gemacht (in denen ich die vom Buch gemachten Punkte in meine eigenen Worte umformuliere, um mein Verständnis zu fördern), und dies ist diejenige, die sich darauf bezieht:
Ich hatte immer das Gefühl, dass ich die fortgeschritteneren Konzepte von Zeigern nicht vollständig erfassen konnte, bis ich etwas so Grundlegendes in meinem Kopf hatte. Es hatte mich nach dieser Aufgabe endlos gestört (was ich übrigens nicht so gut gemacht habe;)), warum "* ip" nicht existierte, nachdem ich "* ip" definiert hatte. Dies zu beherrschen ist wesentlich für fortgeschrittenere Konzepte, die Zeiger wie Funktionszeiger und kompliziertere Definitionen wie diese beinhalten:
Alles in allem denke ich, dass das Konzept der Zeiger Folgendes erfordert:
Grundlegendes Verständnis, wie Speicher in einem Computer angeordnet ist (und was Speicher ist).
Wissen, wie mächtig Zeiger sein können (Verwendung in der realen Welt, nicht nur ein weiteres abstraktes Konzept, das sie zum Zweck des Lernens lernen).
Entschlüsselung der umgangssprachlich als "Definition eines Zeigers" bekannten Hieroglyphen
Alles in allem denke ich, dass es mindestens 3 "Aha" -Momente geben sollte, wenn man etwas über Zeiger lernt. Ich bin noch ein Student, also dachte ich, du würdest die Sichtweise von jemandem schätzen, der noch (relativ) jung ist, das Konzept zu lernen.
quelle
PointerTo<int> a
int* ip
nicht üblicher ist. Ich fing endlich an, Zeiger zu verstehen, als ich Code sah, der so formatiert war. Dann könnte ich es lesen als "IP ist vom Typ Int Zeiger."Zeiger sind ein bisschen wie die Anwendungsverknüpfungen auf Ihrem Desktop. Löschen Sie die Verknüpfung, und das Ziel ist noch vorhanden. Starten Sie die Verknüpfung und das Ziel wird gestartet.
Ich erkläre die Funktionsweise immer, indem ich einfach eine txt-Datei auf meinem Desktop und zwei Verknüpfungen zu der Datei erstelle. Nachdem Sie die Verknüpfungen kopiert und gelöscht haben, können Sie sehen, dass die Leute die Idee hinter "Referenzen" verstehen.
Sobald die Gruppe die Grundlagen der Verknüpfungen verstanden hat, können Sie Zeiger erläutern, wie Sie möchten. Sie werden es wahrscheinlich ziemlich leicht verstehen.
quelle
Vor 8-10 Jahren unterrichtete ich an einem Community College einen Einführungskurs "C". Dies war immer ein lustiges Thema zu erkunden. Was am besten zu funktionieren schien, war, nach ein paar Gesprächen mit einem Kollegen, eine Kaffeetasse und Ihre Hand zu benutzen.
Ich habe die Analogie einer Kaffeetasse (oder einer Reihe davon für Arrays) als Variable verwendet (sie kann etwas enthalten). Ich benutzte dann meine Hand, die auch etwas halten konnte, oder streckte meinen Zeigefinger aus, um auf eine Kaffeetasse zu zeigen.
Eine nahe Hand war null, ein Finger, der auf meinen Kopf zeigte (wie eine Scheinwaffe), war ein baumelnder Zeiger.
Dann mit ein paar Demonstrationen und Reisen durch den Debugger, es hat mit den meisten geklickt.
quelle
Ich mache mir wirklich große Sorgen, wenn ich die Frage "Wie haben Sie die Hinweise verstanden?" Höre. Ich fand das Konzept immer unglaublich einfach und eine logische Weiterentwicklung der Sprachen, die den Programmierern eine große Macht verleiht.
Was mich beunruhigt, ist, dass es mir nie schwer gefallen ist, das Konzept von Zeigern zu verstehen. Also, wenn Sie hier "wann haben Sie es endlich bekommen" immer und immer wieder, beginnen Sie zu denken:
Vielleicht liegt der Grund, warum das Konzept schwierig zu sein scheint, darin, dass wir allen, die noch nicht auf sie gestoßen sind, immer wieder sagen, dass Zeiger so schwierig sind, und hier sind hundert Möglichkeiten, wie Sie lernen können?
Wenn ich diese Idee einfach da rausschmeiße, liebe ich natürlich persönlich ein gutes Diagramm und Steve Gibson macht immer einen fantastischen Job darin, irgendetwas zu erklären !
quelle
Ich hatte nie große Probleme mit Zeigern in C, aber das mag daran liegen, dass ich zuerst Assembler lernen musste. Eigentlich war es eine Erleichterung, Adressen nicht mehr selbst verwalten zu müssen. Vielleicht ist die Antwort (vorausgesetzt, Sie unterrichten dies), den Schülern eine emulierte Assemblersprache zu geben, mit der sie arbeiten können. Sie werden es herausfinden, wenn sie etwas Raffinierteres als "Hallo Welt" schreiben.
quelle
Ein Zeiger ist eine Variable, deren Wert die Speicheradresse einer anderen Variablen ist.
quelle
Wie habe ich wirklich von Zeigern erfahren? Durch das Schreiben eines einfachen Compiler-Studienanfängers.
Wie erklärt man Hinweise in Laienbegriffen? Ich mag die (datierte?) Analogie eines Bibliothekskatalogs, der auf Karteikarten gespeichert ist. Jede Karte ("Zeiger") enthält Informationen darüber, wo sich ein Buch ("Daten") befindet, enthält jedoch nicht das Buch selbst. Wenn Sie die Karte ändern ("Zeigerarithmetik"), ändert sie lediglich das Buch, auf das sie zeigt, und hat keine Auswirkungen auf das Buch selbst. Achten Sie nur darauf, die Adresse nicht zu verfälschen, oder Sie verweisen möglicherweise auf ein nicht vorhandenes Buch oder sogar die falsche Bibliothek. Wenn Sie jedoch der "Adresse" auf der Karte folgen und zum richtigen Teil der Bibliothek gehen ("den Zeiger dereferenzieren"), können Sie das Buch selbst sehen / ändern.
quelle
Ich gehe davon aus, dass jemand, der Zeiger lernen möchte, weiß, was die normalen Variablen sind und wie sie in C funktionieren. Nun wollen wir versuchen, Zeiger mit einigen ihrer Attribute zu definieren.
Sie sind auch Variablen, aber unterschiedlicher Natur. Angenommen, der variable Raum enthält zwei Ebenen. Die normalen Variablen verschiedener Typen befinden sich in der oberen Ebene und die Zeiger in der unteren Ebene. Wie diese Figur-
Wie der Name "Pointer" andeutet, können Zeiger auf etwas zeigen. Als ob unser Finger auf ein Objekt zeigen könnte. Auf was deuten sie hin? Dies sind die normalen Variablen. Kurz gesagt, "Zeiger zeigen auf normale Variablen".
Wie wird ein Zeiger deklariert? Fast wie normale Variablen. Sie müssen dem Namen ein Sternchen (
*
) voranstellen . Mögen-Wie wird dann ein Zeiger einer Variablen zugeordnet? Verwenden Sie den
&
Operator vor der Variablen wie diese Anweisung.Wie wird ein Zeiger verwendet, wenn auf eine Variable gezeigt wird? Dies geschieht auch, indem dem Namen ein Sternchen (
*
) vorangestellt wird . Dann kann es anstelle der Variablen verwendet werden, auf die es jetzt zeigt.Anstatt von
Spielen Sie jetzt mit Zeigern mit etwas Code. Gewöhnen Sie sich jetzt einfach an diese Eigenschaften von Zeigern. Bis zu diesem Punkt sprechen wir darüber, was Zeiger tun. Sobald Sie damit einverstanden sind, beginnen Sie zu untersuchen, wie Zeiger auf eine Variable zeigen und wie sie reagieren, wenn normale arithmetische Operationen auf sie angewendet werden. Gehen Sie dann für die Beziehung zwischen Zeigern und Arrays und Zeigern auf Zeiger.
Das ist alles, was ich über das Lernen von Zeigern vorschlagen werde.
quelle
Bearbeitet zur Unterstützung der überarbeiteten Anforderung der Frage
Mein Weg zum "Post-Pointer" -Verständnis (wenn ich mich richtig erinnere) ging so. Ich hatte einige einfache Erfahrungen mit der Assembler-Programmierung, als ich noch mit einem BBC Micro rumgespielt habe, also hatte ich das Konzept des Speichers als einen Haufen Kisten (siehe unten). Dies wurde durch die Verwendung von Arrays verstärkt. Ich ging jedoch in die Welt von C und musste mich mit Strings auseinandersetzen, was Zeiger bedeutete. In BASIC war das trivial, in Assembler musste ich nie damit arbeiten, und jetzt in Classic C sind es alles Zeiger und so. Ah, aber ich kann zu Arrays mit (nullterminierten) Strings wie folgt zurückkehren:
Schön und gut, das ist nur eine Reihe von Zeichen (8 Bit pro Zeichen in meiner kleinen Welt) mit einem Null-Zeichen am Ende, um zu zeigen, wo es endet. Das printf nimmt nur dieses Array und überläuft es beim Drucken. Aber was ist, wenn ich diesen String in eine Funktion übergeben möchte?
Ist das, was in der Bedienungsanleitung steht, aber worum geht es dabei? Hmm, char * bedeutet "Zeiger auf ein Zeichen". OK ... hat mich verloren. Dann wurde mir klar, dass das Zeichen * p gleich s [0] macht. OK, ich kann das benutzen, aber ich habe immer noch nicht herausgefunden, was Zeiger sind. Ich meine, wie setze ich einige Daten mit einem dieser Dinge? Wieder ab ins Handbuch ...
Während ich das Obige schreibe, sage ich mir "deklariere einen Zeiger auf ein Zeichen und setze ihn gleich diesem Array von Zeichen". Irgendwie macht dieser Zeiger ein Array überflüssig. Vermutlich ist es der Compiler, der zur Abwechslung ein paar Sachen für mich macht. Wie kann ich das Array mit diesem Zeiger ändern? Ich weiß, dass ich die Reihenversion benutzen könnte
aber was ist das Äquivalent in "Zeiger sprechen"? Auf zu diesem Handbuch ...
Ich nehme an, dass * einfach "der Inhalt der Speicheradresse" bedeutet und
(p+2)
ists[2]
. Was bedeutete, dass der Zeiger p ... nur ... eine ... Adresse ... Bong war!Dass es den Klang der Erleuchtung gibt. Ich habe plötzlich Zeiger gezwitschert (es ist lange her, wir Oldtimer "grockten" erst später). Es war nur eine Indirektion.
Original:
OK, mein 2c wert:
Stellen Sie sich vor, das Gedächtnis ist ein Haufen Kisten. Jede Box hat eine Nummer auf der Seite (die Adresse). Jede Box enthält eine Nummer (den Inhalt). Sie können mit diesen Boxen auf zwei Arten arbeiten: Variablen (ich möchte den Inhalt von Box N), Zeiger (ich möchte den Inhalt von Box, was auch immer in Box N ist ). Zeiger sind einfach Indirektion.
Und für die große Antwort, die alles abdeckt, was Sie jemals wissen müssen - lesen Sie dies .
quelle
Hol ein paar kleine Holzklötze.
Fügen Sie Metallhaken an einem Ende und Metallösen am anderen Ende hinzu.
Sie können jetzt eine verknüpfte Liste mit Dingen erstellen, mit denen Sie spielen können.
Versuchen Sie es mit dieser physischen Stütze zu erklären. Ich wünschte mir oft, ich hätte dies getan, als ich den Erstsemester-Schülern Hinweise gab.
Der kleine Metallhaken ist der Zeiger, der Holzblock, auf den das Ding zeigte.
Ich DEFY irgendjemand, um es nicht zu bekommen, nachdem ich mit den Blöcken gespielt habe.
quelle
Ich habe mir das Leben leichter gemacht, als ich einfach alle Flusen entfernt und angefangen habe, den Zeiger als eine andere Variable zu behandeln, anstatt als eine magische Entität (vor langer Zeit in Klasse 11). Ich weiß nur drei Dinge:
Der Rest ist syntaktischer Zucker und gesunder Menschenverstand. Schreiben Sie einfach einige einfache C-Programme (wie das Implementieren einer verknüpften Listenbibliothek), indem Sie Zeiger verwenden, um einen Überblick zu erhalten.
quelle
quelle
Ich kann mich nicht ganz an die Umstände um meinen Zeiger-Aha-Moment erinnern, aber ich habe das Gedächtnis um mein Verständnis eines Arrays im C-Stil nachträglich erweitert. (dh
arr[3]
ist das gleiche wie*(arr+3)
)Aus irgendeinem Grund finde ich es sehr hilfreich, Zeiger als Arrays anzusehen, wenn ich auf eine Zeigersituation stoße.
quelle
Grundsätzlich hat @Gary Rowe das richtige Modell vorgestellt. Speicher als eine Reihe von Feldern mit Adressen (Zahlen) darauf. Jedes Feld speichert einen Wert (Nummer).
Die Idee eines Zeigers besteht darin, den Wert in einem Feld als die Adresse eines anderen Feldes zu interpretieren. Dieser Wert wird verwendet, um auf ein bestimmtes Feld zu verweisen , weshalb er als Referenz bezeichnet wird . Die Dereferenzierung ist somit der Vorgang des Öffnens der Box, auf die verwiesen wird.
Wenn
v
ist eine Variable (Box), dann die Anweisungv
Bedeutet Wert vonv
, dh gib mir was in der Box ist*v
bedeutet dereferenzieren den Wert vonv
, dh gib mir was in der Box steht, auf die sich der Wert von beziehtv
&v
bedeutet referenzv
, dh gib mir die adresse auf boxIch denke, es dient nicht dem Zweck, Zeiger als etwas völlig anderes einzuführen. Es war ein Konzept, das für mich als Kind schwer zu verstehen war. Es schien immer eine dunkle Magie zu sein, die ich nie wirklich verstanden habe und die viele Sonderzeichen brauchte. Das erste Mal, dass ich es verstanden habe, war, als ich ein kleines Spiel mit doppelter Indirektion in einer Sprache schrieb, die keine Zeigerarithmetik hat. Das hat mich aufgeklärt.
Hinweise sind eine Frage der Interpretation. Ich denke, das zu erklären macht die Sache viel einfacher. Und Zeigerarithmetik ist eine äußerst einfache und intuitive Operation, wenn ein einfaches Beispiel mit einem Speicher von 10 Variablen gezeigt wird.
quelle
Die Erklärung, die ich wirklich grocked war:
quelle
Wenn Sie Zeiger erklären möchten, müssen Sie zuerst das Gedächtnis erklären. Ich mache das normalerweise mit Millimeterpapier / Karopapier mit Zeilen und Spalten. Wenn die "Studentin" das Gedächtnis versteht, kann sie verstehen, was eine Adresse ist. Wenn Sie Adresse haben, haben Sie Zeiger.
Sie können mit dieser Abstraktion spielen. ZB schreiben Sie die Adresse (Nummer) eines Quadrats in ein anderes Quadrat. Zeichnen Sie nun einen Pfeil vom Zeigerfeld zum Zielfeld. Überschreiben Sie nun den Zeiger (z. B. inkrementieren Sie ihn) und passen Sie den Pfeil an. Schreiben Sie eine Adresse in ein anderes Feld und lassen Sie den Schüler den Pfeil zeichnen ...
Nächster Schritt: Geben Sie bestimmten Quadraten (wie dem Zeiger) einen Namen. Jetzt können Sie die Dereferenzierung erklären. Das ist es.
quelle
Vielleicht bin es nur ich, aber ich arbeite gut mit Analogien. Nehmen wir also an, Sie haben einen Freund (Funktion / Klasse) "Foo", der möchte, dass sich jemand anderes (andere Funktion / Klasse), "Bar", mit Ihnen aus irgendeinem Grund in Verbindung setzt. "Foo" könnte dich dazu bringen, "Bar" zu besuchen, aber das ist nicht bequem, all diese Wesen (Instanzen) herumzubewegen. Allerdings könnte "Foo" "Bar" Ihre Telefonnummer (Zeiger) senden. So weiß "Foo", egal wo Sie sich befinden, wie Sie sich mit Ihnen in Verbindung setzen können, ohne Sie finden zu müssen.
Angenommen, "Bar" hat einen Bekannten, "Baz", der sich ebenfalls mit Ihnen in Verbindung setzen möchte. Aber Sie schützen Ihre Telefonnummer und möchten nicht, dass alle diese haben. "Baz" kann "Bar" (Telefon als Zeiger) anrufen, der den Anruf dann an Sie weiterleiten kann (ein anderer Zeiger). Und so weiter und so fort in der Kette der Freunde und Freunde von "Baz".
quelle
Pointers macht Weg mehr Sinn , wenn Sie Assembler - Sprache und / oder Computerarchitektur studiert haben. Ich denke, wenn ich eine C-Klasse unterrichte, würde ich mit ein paar Wochen Architektur beginnen, um das Speichermodell und die Arten von Anweisungen zu erklären, die der Prozessor tatsächlich ausführt.
quelle
Mein "aha!" Moment kam in diesem Tutorial:
Ein Tutorial zu Zeigern und Arrays in C
Um genau zu sein, kam es in diesem Kapitel: Kapitel 3: Zeiger und Strings
Genauer gesagt kam es mit diesem Satz:
Als ich das las, teilten sich die Wolken und Engel bliesen Trompetenfanfaren.
Wie Sie sehen, hatte jedes C-Tutorial oder Buch, das ich zuvor gelesen hatte, behauptet, dass C nach Wert oder Referenz eine schändliche Lüge sein könnte. Die Wahrheit ist, dass C immer als Wert übergeben wird, aber manchmal handelt es sich bei dem übergebenen Wert zufällig um eine Adresse. Innerhalb der Methode wird eine Kopie dieser Adresse erstellt, genau wie eine Kopie eines übergebenen Int. Eine Kopie des Werts, auf den der Zeiger zeigt, wird nicht erstellt. Mit dem Zeiger innerhalb der Methode können Sie also auf den ursprünglichen Wert zugreifen und diesen ändern.
Ich wurde nie ein C-Programmierer, aber ich wurde ein .NET-Programmierer, und Objekte und Objektreferenzen funktionieren auf die gleiche Weise. Der Verweis auf das Objekt wird als Wert übergeben (und somit kopiert), das Objekt selbst wird jedoch nicht kopiert. Ich habe mit vielen Programmierern gearbeitet, die das nicht verstehen, weil sie nie Zeiger gelernt haben.
quelle
Der Trick besteht darin, zu erklären, dass der Ort eines Objekts und das Objekt selbst nicht gleich sind, genau wie ein Bild einer Pfeife keine Pfeife ist . Wenn Sie ein Objekt verschieben, ändert sich seine Position. Der Ort bleibt und etwas anderes kann dort gestellt werden.
quelle
Ein Zeiger ist eine Notiz, die Ihnen sagt, wo etwas Nützliches ist. Es enthält die Position des Objekts und gibt an, wie groß das Objekt ist (jedenfalls in C). Ein Doppelzeiger ist also wie eine Haftnotiz mit der Aufschrift "Im Kühlschrank ist ein Sechserpack". Um herauszufinden, ob es sich um Cola oder Budweiser handelt, muss man das Sixpack holen.
quelle
Angesichts des Codes:
int v=42;
// Deklarieren und Initialisieren einer einfachen Variablenint *p = &v;
// Erzeugen eines Punktes p auf die Variable vÜber den obigen Code kann folgendes gesagt werden:
int * p
// "int pointer p" ... so deklarieren Sie einen Zeiger auf eine Variable vom Typ int*p
// "wies auf p" ... das sind die Daten, auf die p zeigt, dasselbe wie v.&v
// "Adresse der Variablen v" ... das ist der Literalwert für pquelle
http://cslibrary.stanford.edu/
Diese Site bietet großartige Tutorials für Lernhinweise und Speicherverwaltung.
Ich würde vorschlagen, dass Sie die Grundlagen, die Zeiger und den Speicher, die auf der Site angegeben sind, durchgehen. Sie können sich auch die Probleme mit verknüpften Listen ansehen, die auf dem Link angegeben sind, um die Zeigerkonzepte weiter zu stärken.
quelle
Der Schlüssel zum Erklären von Zeigern besteht darin, sicherzustellen, dass die Personen, denen Sie erklären, das Konzept des Gedächtnisses bereits verstehen. Es wäre zwar schön, wenn sie es auf niedriger Ebene wirklich verstanden hätten, aber es reicht aus, zu glauben, dass Speicher als massives Array vorhanden ist, und zu verstehen, dass Sie über seine Indexposition auf jede Position im Array zugreifen können.
Der nächste Schritt besteht für die meisten Menschen darin, den Indexstandort zu übergeben, anstatt den gesamten Speicher zu kopieren. Und das reicht aus, damit die meisten Menschen verstehen, warum Zeiger nützlich sind.
Der letzte Schritt zum Verstehen von Zeigern besteht darin, zu erklären, wie Sie als Parameter einen Speicherindexort für die Methode übergeben können, um den Indexort zu speichern, an dem alle Daten gespeichert sind. Ich habe festgestellt, dass dies für manche Menschen zu weit gehen kann.
Sobald jemand diese grundlegenden Schritte verstanden hat, kann er sofort feststellen, dass Sie Zeiger auf unbestimmte Zeit verketten können, solange Sie nachverfolgen, wie oft Sie nach Adressen suchen müssen, um das eigentliche Datenobjekt zu finden.
Sobald jemand Zeiger erfasst hat, muss er als Nächstes schnell den Unterschied zwischen Heapspeicher und Stapelspeicher erkennen und herausfinden, warum Zeiger zum Stapeln von Speicher gefährlich sind, wenn sie außerhalb der Methode übergeben werden.
quelle
Ich erinnere mich an ein Buch "C-Rätsel" oder ähnliches, das ich nur las, weil es eines der wenigen programmier- / computerbezogenen Bücher in der Bibliothek war. Mein Verständnis von C war rudimentär. Es warf eine C-Expresison auf Sie und bat Sie, sie zu untersuchen, was immer komplizierter wurde.
quelle
Als ich an der Universität war, hatte mein Professor einige wirklich nette Powerpoint-Folien, auf denen ein Punkt als separate Variable mit einem Pfeil zu einem Speicherort (dargestellt wie ein Array) dargestellt war, und als wir verknüpfte Listen machten, tat er es Schritt für Schritt - Schritt für Schritt: Zeigt an, wann sich der Pfeil ändert, wann der Zeiger dereferenziert wird usw. - Es gab keine Möglichkeit, dass man es innerhalb weniger Minuten nicht verstehen konnte. Das Konzept selbst ist sehr einfach, aber es richtig zu machen oder es in praktischen Programmen anzuwenden, erfordert mehr Übung.
quelle
Bevor ich das tue, erkläre ich, dass bei der Programmierung "alles Speicher verwendet" und (statische) Variablenzuweisung im Speicher. Ich werde auch erklären, was eine Speicheradresse ist, und die Beziehung zwischen Speicherplatz, Speicheradresse und Variablen.
Schließlich erkläre ich, dass es Integer-Datentypen und -Variablen, String-Datentypen und -Variablen usw. gibt, bis ich erkläre, dass es einen speziellen Datentyp gibt, der Speicheradressen speichert und einen leeren Wert wie "0" hat. genannt null .
Und schließlich dynamisch zugewiesene Variablen durch die Verwendung von Zeigern.
quelle