|
auf Anhieb richtig lesen kannst, dann geh zurück zur vorhergehenden Seite und such Dir ein neues Thema, oder verbesser die Ausführungen hier.
Obige Deklaration ließe sich auf verschiedene Arten interpretieren, die Frage ist hier aber natürlich, wie interpretiert sie der Compiler. Um zu verstehen wie man diese Deklaration lesen sollte, muß man sich vorher ansehen welche Operatoren hier verwendet werden. Eine weitere Schwierigkeit für Neulinge schleicht sich an dieser Stelle ein. Hier wird ausgerechnet ein Operator verwendet der an anderer Stelle im einem Programm auch andere Funktionalität hat. Der * Operator erzeugt an dieser Stelle wie es bekannt sein sollte einen Zeiger auf ein Objekt on einem bestimmten Typ.
Was muß man noch unterscheiden? Es gibt Klammern die eine Deklaration gruppieren, so wie das in echtem Code auch der Fall ist und es gibt Klammer die Anzeigen, daß es sich bei diesem Symbol um eine Funktion handelt. Alle Operatoren die in Deklarationen verwendet werden, sind nach der Reihenfolge Ihrer Priorität abzuarbeiten. Die Priorität (im englischen precedence) aller Operatoren ist in jedem guten C Buch abgedruckt. Hier nur in Kürze für alle in Declarationen verwendeten Operatoren:
|
Hier noch ein paar zum Üben und Zähne ausbeißen:
|
Zu guter Letzt sei hier noch der Hinweis auf das Unix Utility cdecl angeführt. Mit diesem Programm kann man solche Deklarationen leicht lesen aber auch selbst leicht erzeugen, vorausgesetzt man ist in der Lage die Deklaration in englisch zu formulieren.
-- ZoranCutura
Diskussionen |
Ich möchte hier mal einen Beitrag von Niklas Matthies aus de.comp.lang.iso-c++ zu dem Thema zitieren und zur Diskussion stellen, da sein Ansatz für mich einfacher/verständlicher wirkt:
"Die Deklarationen sind nicht so schwierig zu lesen, es gilt eine einfache rechts-vor-links-Regel: d. h. man geht, ausgehend vom deklarierten Namen, grundsätzlich erstmal nach rechts. Wenn man auf eine schließende Klammer oder das Ende der Deklaration trifft, macht man nach links weiter. Wenn man dabei auf eine öffnende Klammer trifft macht man wieder nach rechts bei der entsprechenden schließenden Klammer weiter. Dabei zählt man einfach alles auf, was man antrifft, und bekommt dabei eine natürlichsprachige Beschreibung des Typs. Beispiel:
|
Wir fangen beim `x' an:
"x ist ein "Wir gehen nach rechts und stoßen auf eine schließende Klammer, also machen wir links weiter, wo ein `*' (Pointer) ist, also:
"Pointer auf ein "Wir gehen weiter nach links und stoßen auf eine öffnende Klammer, also machen wir bei der entsprechenden schließenden Klammer wieder nach rechts weiter, wo wir auf `[4]' stoßen, also:
"Array von 4 "Wir gehen weiter nach rechts und stoßen auf das Ende der Deklaration, also machen wir nach links weiter, d. h. von der öffnenden Klammer aus, wo wir auf `int' stoßen, also:
"int"Wir gehen weiter nach links und stoßen auf das Ende (bzw. den Anfang) der Deklaration, also sind wir fertig:
"x ist ein Pointer auf ein Array von 4 int"Und bei
|
x "x ist ein " x[4] "Array von 4 " *x[4]; "Pointer auf ein " int *x[4]; "int"Bei Funktionsparametern muß für jeden Parameter auch in der "Mitte" des Ausdrucks anfangen, also da, wo der Name des Parameters stehen würde (oder eventuell sogar steht), und dort nach demselben Prinzip vorgehen. Beispiel:
|
x "x ist eine " x( "Funktion mit Parametern (" x( * "Pointer auf " x( (*)[] "Array von " x( *(*)[] "Pointern auf " x(int *(*)[], "int, " x(int *(*)[], * "Pointer auf " x(int *(*)[], (*)[5] "Array von 5 " x(int *(*)[], *(*)[5]) "Pointern auf " x(int *(*)[], (*(*)[5])( "Funktion mit Parametern (" x(int *(*)[], (*(*)[5])( * "Pointer auf " x(int *(*)[], (*(*)[5])(int*) "int) " x(int *(*)[], int (*(*)[5])(int*)) "und Rückgabetyp int) " *x(int *(*)[], int (*(*)[5])(int*)) "und Rückgabetyp Pointer auf " void *x(int *(*)[], int (*(*)[5])(int*)); "void"Gerade die rechts-vor-links-Regel kommt bei deinem Ansatz IMHO nicht so klar heraus -- ChristianDühl
Der rechts-vor-links-Regel sollte dadurch Folge geleistet sein sein, daß man ja zuerst die Postfix-Operatoren bearbeitet. In "deiner" Version vermisse ich eine wichtige Sache, naehmlich die Assoziativität bei Deklarationen von Feldern oder Pointern. Es sollte für den Lesenden wichtig sein ob
|
ein Zeiger auf einen const-Zeiger auf auf char ist, oder ein const-Zeiger auf einen Zeiger auf char. Darauf sollte noch irgendwie hingewiesen werden.
Gleiches gilt fuer:
|
--zc
|
Möglicherweise haben diverse Leute diese Regeln aus meiner c.htm gelernt, nämlich nachdem die etwa 1000 Zugriffe hatte, tauchten überall diese Erklärungen auf, die meinen Erklärungen in c.htm sehr ähnlich sind und gleiche prägnante und kennzeichnende Formulierungen verwenden. --hs
Helmut, ich habe dein Tutorial oder wie Du es nennen möchtest bis heute noch nicht gelesen und kann deshalb behaupten hier keine deiner prägnanten und kennzeichnenden Formulierungen zu verwenden. Meine Zusammenfassung stammt weitestgehend aus Peter van der Linden's "Expert C Programming". Wenn auch nicht so vollständig wie bei Peter. --zc