Ich fand die von Bruce Eckel beschriebene Methode hilfreich und leicht zu befolgen:
Funktionszeiger definieren
Um einen Zeiger auf eine Funktion zu definieren, die keine Argumente und keinen Rückgabewert enthält, sagen Sie:
void (*funcPtr)();
Wenn Sie sich eine komplexe Definition wie diese ansehen, ist der beste Weg, sie anzugreifen, in der Mitte zu beginnen und sich herauszuarbeiten. "In der Mitte beginnen" bedeutet, mit dem Variablennamen funcPtr zu beginnen. „Ausarbeiten“ bedeutet, nach rechts nach dem nächsten Element zu suchen (in diesem Fall nichts; die rechte Klammer hält Sie kurz), dann nach links zu schauen (ein durch das Sternchen gekennzeichneter Zeiger) und dann nach rechts zu schauen (an leere Argumentliste, die eine Funktion angibt, die keine Argumente akzeptiert), dann nach links schauen (void, was anzeigt, dass die Funktion keinen Rückgabewert hat). Diese Bewegung von rechts nach links nach rechts funktioniert mit den meisten Deklarationen.
Um zu überprüfen, "beginne in der Mitte" ("funcPtr ist ein ..."), gehe nach rechts (nichts dort - du wirst durch die rechte Klammer gestoppt), gehe nach links und finde das '*' (" ... Zeiger auf ein ... ”), gehe nach rechts und finde die leere Argumentliste (“ ... Funktion, die keine Argumente akzeptiert ... ”), gehe nach links und finde die Leere (“ funcPtr is ein Zeiger auf eine Funktion, die keine Argumente akzeptiert und void zurückgibt ”).
Sie fragen sich vielleicht, warum * funcPtr Klammern erfordert. Wenn Sie sie nicht verwenden würden, würde der Compiler Folgendes sehen:
void *funcPtr();
Sie würden eine Funktion deklarieren (die eine Leere * zurückgibt), anstatt eine Variable zu definieren. Sie können sich vorstellen, dass der Compiler denselben Prozess durchläuft, den Sie ausführen, wenn er herausfindet, was eine Deklaration oder Definition sein soll. Diese Klammern müssen „gegen“ stoßen, damit sie nach links zurückkehren und das '*' finden, anstatt nach rechts fortzufahren und die leere Argumentliste zu finden.
Komplizierte Erklärungen und Definitionen
Abgesehen davon können Sie, sobald Sie herausgefunden haben, wie die C- und C ++ - Deklarationssyntax funktioniert, viel kompliziertere Elemente erstellen. Zum Beispiel:
//: C03:ComplicatedDefinitions.cpp
/* 1. */ void * (*(*fp1)(int))[10];
/* 2. */ float (*(*fp2)(int,int,float))(int);
/* 3. */ typedef double (*(*(*fp3)())[10])();
fp3 a;
/* 4. */ int (*(*f4())[10])();
int main() {} ///:~
Gehen Sie durch jeden einzelnen und verwenden Sie die Rechts-Links-Richtlinie, um dies herauszufinden. Nummer 1 besagt, dass "fp1 ein Zeiger auf eine Funktion ist, die ein ganzzahliges Argument verwendet und einen Zeiger auf ein Array von 10 ungültigen Zeigern zurückgibt."
Nummer 2 besagt: "fp2 ist ein Zeiger auf eine Funktion, die drei Argumente (int, int und float) akzeptiert und einen Zeiger auf eine Funktion zurückgibt, die ein ganzzahliges Argument verwendet und ein float zurückgibt."
Wenn Sie viele komplizierte Definitionen erstellen, möchten Sie möglicherweise ein typedef verwenden. Nummer 3 zeigt, wie ein typedef das Eingeben der komplizierten Beschreibung jedes Mal speichert. Es heißt: "Ein fp3 ist ein Zeiger auf eine Funktion, die keine Argumente akzeptiert und einen Zeiger auf ein Array von 10 Zeigern auf Funktionen zurückgibt, die keine Argumente annehmen und Doppelte zurückgeben." Dann heißt es: "a ist einer dieser fp3-Typen." typedef ist im Allgemeinen nützlich, um komplizierte Beschreibungen aus einfachen zu erstellen.
Nummer 4 ist eine Funktionsdeklaration anstelle einer Variablendefinition. Es heißt: "f4 ist eine Funktion, die einen Zeiger auf ein Array von 10 Zeigern auf Funktionen zurückgibt, die ganze Zahlen zurückgeben."
Sie werden selten oder nie so komplizierte Erklärungen und Definitionen wie diese benötigen. Wenn Sie jedoch die Übung durchlaufen, sie herauszufinden, werden Sie nicht einmal leicht durch die etwas komplizierten gestört, denen Sie im wirklichen Leben begegnen können.