2013-01-01 4 views
16

Meine Frage ist sehr einfach.C-Funktion Pointer-Syntax

normalerweise, wenn eine Variable deklarieren, setzen Sie seine Art, bevor es, wie:

int a; 

ein Funktionszeiger kann Typ wie haben: int (*) (int, int), falls wir darauf hinweisen, eine Funktion, die zwei int und einen int zurückgibt. Aber, wenn solch ein Zeiger deklarieren, ist seine Kennung nicht nach der Art, wie:

int(*)(int,int) mypointer; 

statt, müssen Sie die Kennung in der Mitte schreiben:

int(*mypointer)(int,int); 

warum ist das so? Sorry, ich weiß, es ist eine peinlich einfache Frage ...

Danke an alle für die Antwort. A.S.

+3

Das ist nicht der einzige Fall, Sie verwenden diesen Stil auch in Array-Deklarationen. – effeffe

+2

Suche nach "Deklaration spiegelt Verwendung wider". –

Antwort

7

Diese Struktur gibt an, wie eine normale Funktion deklariert (und verwendet) wird.

eine normale Funktionsdefinition vor:

int foo (int bar, int baz, int quux); 

nun einen Funktionszeiger auf eine Funktion der gleichen Signatur prüfen zu definieren:

int (*foo) (int, int, int); 

Beachten Sie, wie sich die beiden Strukturen spiegeln einander? Das macht *foo viel einfacher als Funktionszeiger und nicht als etwas anderes zu identifizieren.

11

erkläre ich dies in meiner Antwort auf Why was the C syntax for arrays, pointers, and functions designed this way?, und es kommt im Grunde nach unten zu:

die Sprache Autoren die Syntax Variable-centric anstatt Typ-centric machen bevorzugt. Das heißt, sie wollten, dass ein Programmierer die Deklaration betrachtet und denkt: "Wenn ich den Ausdruck *func(arg) schreibe, würde das zu einem int führen; wenn ich *arg[N] schreibe, habe ich einen Gleitkommazahlen" anstatt "func muss ein Zeiger sein eine Funktion, die diese nimmt und zurückgibt, die ".

Die C entry on Wikipedia behauptet, dass:

Ritchie Idee ähnelt Identifikatoren in Kontexten, deren Nutzung zu erklären war: „Erklärung Verwendung widerspiegelt“.

... zitiert p122 von K & R2.

3

Wenn Sie mit einer Funktion arbeiten (kein Zeiger auf einen), ist der Name auch in der Mitte. Es geht wie folgt: return-type function-name "(" argument-list ")" .... Zum Beispiel ist in int foo(int), int der Rückgabetyp, foo der Name und int die Argumentliste.

Ein Zeiger auf eine Funktion funktioniert auf die gleiche Weise - Rückgabetyp, dann Name, dann Argumentliste.In diesem Fall müssen wir ein * hinzufügen, um es zu einem Zeiger zu machen, und (da die * für einen Zeiger ist Präfix) ein Paar Klammern, um die * an den Namen anstelle des Rückgabetyps zu binden. Zum Beispiel würde int *foo(int) eine Funktion namens foo bedeuten, die einen int-Parameter akzeptiert und einen Zeiger auf einen int zurückgibt. Um stattdessen das * an foo zu binden, benötigen wir Klammern, die int (*foo)(int) geben.

Dies wird besonders hässlich, wenn Sie ein Array von Zeigern auf Funktionen benötigen. In einem solchen Fall finden die meisten Menschen ist es am einfachsten, ein typedef für den Zeigertyp zu verwenden, dann eine Reihe von dieser Art erstellen:

typedef int (*fptr)(int); 

fptr array[10]; 
1

ich an einigen Stellen Funktionszeiger deklariert werden als

int gesehen hatte (* foo) (int a, int b);

und an einigen Stellen werden a und b nicht erwähnt und beide funktionieren noch.

so int (* foo) (int, int) ist auch korrekt.

Sehr einfache Art und Weise, die ich erinnere mich gefunden, wie unten

suppose Funktion wird erklärt, wie erwähnt ist: int Funktion (int a, int b); Schritt1 - einfach Funktion in paranthases setzen: int (Funktion) (int a, int b); Step2- Platzieren Sie ein * vor dem Funktionsnamen und ändern Sie den Namen: int (* funcPntr) (int a, int b);

PS: Ich befolge keine korrekten Kodierungsrichtlinien für Namenskonventionen usw. in dieser Antwort.