Ich hatte kürzlich das Vergnügen, einem C-Programmier-Anfänger Hinweise zu erklären, und bin auf die folgende Schwierigkeit gestoßen. Es scheint vielleicht überhaupt kein Problem zu sein, wenn Sie bereits wissen, wie man Zeiger verwendet, aber versuchen Sie, das folgende Beispiel mit klarem Verstand zu betrachten:
int foo = 1;
int *bar = &foo;
printf("%p\n", (void *)&foo);
printf("%i\n", *bar);
Für den absoluten Anfänger könnte die Ausgabe überraschend sein. In Zeile 2 hatte er / sie gerade * bar als & foo deklariert, aber in Zeile 4 stellte sich heraus, dass * bar tatsächlich foo statt & foo ist!
Die Verwirrung, könnte man sagen, ergibt sich aus der Mehrdeutigkeit des Symbols *: In Zeile 2 wird ein Zeiger deklariert. In Zeile 4 wird es als unärer Operator verwendet, der den Wert abruft, auf den der Zeiger zeigt. Zwei verschiedene Dinge, richtig?
Diese "Erklärung" hilft einem Anfänger jedoch überhaupt nicht. Es wird ein neues Konzept eingeführt, indem auf eine subtile Diskrepanz hingewiesen wird. Dies kann nicht der richtige Weg sein, es zu lehren.
Wie haben Kernighan und Ritchie das erklärt?
Der unäre Operator * ist der Indirektions- oder Dereferenzierungsoperator. Wenn es auf einen Zeiger angewendet wird, greift es auf das Objekt zu, auf das der Zeiger zeigt. […]
Die Deklaration des Zeigers ip
int *ipist als Mnemonik gedacht; es heißt, dass der Ausdruck*ipein int ist. Die Syntax der Deklaration für eine Variable ahmt die Syntax der Ausdrücke nach, in denen die Variable möglicherweise erscheint .
int *ipsollte gelesen werden wie " *ipwird ein int" zurückgeben? Aber warum folgt dann die Zuordnung nach der Deklaration nicht diesem Muster? Was ist, wenn ein Anfänger die Variable initialisieren möchte? int *ip = 1(read: *ipgibt ein intund das intis zurück 1) funktioniert nicht wie erwartet. Das konzeptionelle Modell scheint einfach nicht kohärent zu sein. Vermisse ich hier etwas?
Bearbeiten: Es wurde versucht, die Antworten hier zusammenzufassen .
*eine Deklaration ein Token ist, das "einen Zeiger deklarieren" bedeutet, in Ausdrücken der Dereferenzierungsoperator ist und dass diese beiden verschiedene Dinge darstellen, die zufällig dasselbe Symbol haben (wie der Multiplikationsoperator - gleiches Symbol, andere Bedeutung). Es ist verwirrend, aber alles andere als der tatsächliche Zustand wird noch schlimmer sein.
int* barmacht es das Schreiben so, dass es offensichtlicher wird, dass der Stern tatsächlich Teil des Typs ist, nicht Teil des Bezeichners. Natürlich stößt dies auf verschiedene Probleme mit unintuitiven Dingen wie int* a, b.
*kann je nach Kontext zwei verschiedene Bedeutungen haben. Genauso wie derselbe Buchstabe je nach Wort unterschiedlich ausgesprochen werden kann, was es schwierig macht, das Sprechen vieler Sprachen zu lernen. Wenn jedes einzelne Konzept / jede Operation ein eigenes Symbol hätte, würden wir viel größere Tastaturen benötigen, sodass Symbole recycelt werden, wenn dies sinnvoll ist.
int* p), während Sie Ihren Schüler davor warnen , mehrere Deklarationen in derselben Zeile zu verwenden, wenn Zeiger beteiligt sind. Wenn der Schüler das Konzept der Zeiger vollständig verstanden hat, erklären Sie dem Schüler, dass die int *pSyntax is äquivalent ist, und erklären Sie dann das Problem mit mehreren Deklarationen.


