Ich habe gerade einen Code im Internet durchgesehen und Folgendes gefunden:
float * (*(*foo())[SIZE][SIZE])()
Wie lese ich diese Erklärung? Gibt es bestimmte Regeln zum Lesen derart komplexer Erklärungen?
c++
c
function-pointers
declaration
Kaunteya
quelle
quelle
Antworten:
Ich habe das schon eine Weile nicht mehr gemacht!
Beginnen Sie mit
foo
und gehen Sie nach rechts.float * (*(*
foo()
)[SIZE][SIZE])()
Kann nicht richtig gehen, da es eine schließende Klammer gibt. Geh nach links:
float * (*(
* foo()
)[SIZE][SIZE])()
Ich kann nicht weiter nach links gehen, also kreuzen wir die Klammern und gehen wieder nach rechts
float * (*
(* foo())
[SIZE][SIZE])()
float * (*
(* foo())[SIZE]
[SIZE])()
float * (*
(* foo())[SIZE][SIZE]
)()
Schließende Klammer erreicht, wieder links, um ein Zeigersymbol zu erreichen:
float * (
*(* foo())[SIZE][SIZE]
)()
Wieder die linke Klammer, also kreuzen wir sie und gehen wieder nach rechts:
float *
( *(* foo())[SIZE][SIZE])
()
float *
( *(* foo())[SIZE][SIZE])()
Und bis zum Ende gelassen
float * ( *(* foo())[SIZE][SIZE])()
Und wer auch immer das geschrieben hat, bitte bringen Sie ihm bei, Folgendes zu verwenden
typedef
:// Function that returns a pointer to float typedef float* PFloatFunc (); // Array of pointers to PFloatFunc functions typedef PFloatFunc* PFloatFuncArray2D[SIZE][SIZE]; // Function that returns a pointer to a PFloatFuncArray2D PFloatFuncArray2D* foo();
quelle
Standardregel: Finden Sie die Kennung ganz links und arbeiten Sie sich heraus, merken Sie sich das
[]
und()
binden Sie vorher*
:foo -- foo foo() -- is a function *foo() -- returning a pointer (*foo())[SIZE] -- to a SIZE-element array (*foo())[SIZE][SIZE] -- of SIZE-element arrays *(*foo())[SIZE][SIZE] -- of pointers (*(*foo())[SIZE][SIZE])() -- to functions * (*(*foo())[SIZE][SIZE])() -- returning pointers float * (*(*foo())[SIZE][SIZE])(); -- to float
Stellen Sie sich vor, Sie haben eine Reihe von Funktionen, die Zeiger zurückgeben auf
float
:float *quux(); float *bar(); float *bletch(); float *blurga();
Angenommen, Sie möchten sie in einer 2x2-Tabelle speichern:
float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
tab
ist ein SIZE x SIZE-Array von Zeigern auf Funktionen, auf die Zeiger zurückgegeben werdenfloat
.Nun wollen wir entscheiden, dass eine Funktion einen Zeiger auf diese Tabelle zurückgibt:
float *(*(*foo())[SIZE][SIZE])() { static float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga}; return &tab; }
Beachten Sie, dass Sie mehrere Funktionen haben können, die Tabellen mit unterschiedlichen Funktionen erstellen oder dieselben Funktionen unterschiedlich organisieren:
float *(*(*qwerbl())[SIZE][SIZE])() { static float *(*tab[SIZE][SIZE])() = {blurga, bletch, bar, quux}; return tab; }
Das ist der einzige Grund, warum ich mir so etwas vorstellen kann. Sie sollten solche Typen nicht sehr oft in freier Wildbahn sehen (obwohl sie gelegentlich auftauchen und ich mich schuldig gemacht habe, etwas ähnlich Abscheuliches geschrieben zu haben).
quelle
Laut cdecl.org
Verwenden Sie die Spiralregel von Luchian Grigore, wenn Sie sie von Hand dekodieren möchten.
quelle
Am besten konvertieren Sie hier in eine Reihe von Typedefs.
typedef float * fnReturningPointerToFloat(); typedef fnReturningPointerToFloat* fnArray[SIZE][SIZE]; fnArray* foo();
quelle
Im Allgemeinen könnten Sie cdecl.org ausprobieren, aber Sie müssten es ersetzen
SIZE
Angenommen, Sie tauschen
SIZE
gegen 12, dann erhalten Sie:Ich bin mir nicht sicher, ob dir das wirklich hilft!
Zwei Beobachtungen hier:
quelle
Dieses Dokument gibt mir den besten Hinweis darauf, wie ich eine C-Deklaration einfach erstellen kann:
http://c-faq.com/decl/spiral.anderson.html
Beispiel:
+-------+ | +-+ | | ^ | | char *str[10]; ^ ^ | | | +---+ | +-----------+ Question we ask ourselves: What is str? ``str is an... - We move in a spiral clockwise direction starting with `str' and the first character we see is a `[' so, that means we have an array, so... ``str is an array 10 of... - Continue in a spiral clockwise direction, and the next thing we encounter is the `*' so, that means we have pointers, so... ``str is an array 10 of pointers to... - Continue in a spiral direction and we see the end of the line (the `;'), so keep going and we get to the type `char', so... ``str is an array 10 of pointers to char'' We have now ``visited'' every token; therefore we are done!
quelle
Obwohl die meisten der obigen Antworten gut genug sind, fehlen vollständige Regeln für die Dekodierung komplexer C-Deklarationen. Ich habe unten einen vollständigen Satz bereitgestellt, um jede komplexe C-Deklaration zu dekodieren. Dieses Regelwerk basiert tatsächlich auf der Priorität von Operatoren. Regeln wie rechte Spiralregeln können als Abkürzung für diese Regeln angesehen werden.
Vor allem müssen wir einige Dinge wissen, um die Deklaration zu entschlüsseln.
'Grundtyp' einer Erklärung
Die AC-Deklaration hat immer nur einen grundlegenden Deklarationstyp. Dies ist die am weitesten links stehende Position einer Erklärung. Zum Beispiel -
int a
- Grundtyp ist 'int'float *p
- Grundtyp ist 'float'char (*p)[3]
- Grundtyp ist 'char'Vorrang und Assoziativität
Als nächstes müssen wir die Rangfolge der wissen
()
,[]
und*
- Dereferenzierungsoperator()
,[]
- Assoziativität ist von links nach rechts*
- Assoziativität ist von rechts nach linksPhrase, die jedem der obigen Operatoren entspricht
Als nächstes müssen wir die decodierte Phrase kennen, die jedem Operator entspricht. Beispiele werden diesen Punkt klar machen.
()
- Funktionsrückgabe[SIZE]
- Array von GRÖSSE*
- Zeiger aufBefolgen Sie nun die folgenden Regeln, um die Deklaration zu dekodieren
Schreiben Sie immer zuerst den Variablennamen, gefolgt von einem 'ist'.
Zum Beispiel -
int a
- a ist ...float *p
- p ist ...char (*p)[3]
- p ist ...Beenden Sie immer mit dem Basistyp
Zum Beispiel -
int a
- a ist ... intfloat *p
- p ist ... schwebenchar (*p)[3]
- p ist ... charFüllen Sie nun den Teil dazwischen mit den folgenden Unterschritten
Folgen Sie ausgehend vom Namen der Priorität und Assoziativität des Operators, um den Operator mit der nächsthöheren Priorität auszuwählen, und hängen Sie die entsprechende Phrase an den mittleren Teil der decodierten Zeichenfolge an.
Wiederholen Sie den obigen Unterschritt für die verbleibende Deklaration, bis der Dekodierungsprozess abgeschlossen ist
ANMERKUNG 1: Der Einfachheit halber habe ich die Argumente der Funktion ignoriert, sie können jedoch direkt nach der entsprechenden Phrase eingefügt werden
()
.ANMERKUNG 2: Parenthesis (
()
) ändert die Prioritätsreihenfolge von Operatoren wie bei jedem arithmetischen Ausdruck.ANMERKUNG 3: Sie können in der dekodierten Deklaration Klammern verwenden, um die Lesbarkeit zu verbessern (ich habe dies in einigen Beispielen unten getan). Stellen Sie sich jede Menge von () als eine Einheit vor.
ANMERKUNG 4: Ein n-dimensionales Array ist tatsächlich ein Array von Arrays von ... (n-1-mal) Arrays . Zum Beispiel ist A [2] [3] - A ein Array von 2 (Array von 3 int), dh A ist ein Array von 2 Elementen, wobei jedes Element ein Array ist, das 3 ganze Zahlen enthält
Beispiele
int a
- a ist intfloat *p
- p ist der Zeiger auf floatchar (*p)[3]
- p ist ein Zeiger auf ein Array mit 3 ZeichenEinige komplexe Deklarationsbeispiele
int **p[10]
- p ist ein Array von 10 Zeigern auf Zeiger auf intint (*p)[10]
- p ist ein Zeiger auf ein Array von 10 intint *p(char *a)
- p ist ein Funktionsrückgabezeiger auf intint (*p(char*a))[10]
- p gibt die Funktion zurück (Zeiger auf (Array von 10 int))int *(*p)()
- p ist Zeiger auf (Funktionsrückgabe (Zeiger auf int))int (*p()[20])[10]
- p ist eine Funktionsrückgabe (Array von 20 (Zeiger auf (Array von 10 int)))Dieser Regelsatz kann auch mit verwendet werden
const
- const qualifier ändert den Begriff links davon (falls vorhanden), andernfalls ändert er den Begriff rechts davon.const int *p[10]
- p ist ein Array von 10 Zeigern auf int constint const *p[10]
- p ist ein Array mit 10 Zeigern auf const int (dies entspricht dem 7. Beispiel).int *const p[10]
- p ist ein Array von 10 const Zeigern auf intNun ein wirklich komplexes Beispiel, das in der Praxis nirgendwo Verwendung findet, aber dennoch zur Demonstration des Dekodierungsprozesses verwendet werden kann
char *(*(**foo[][8])())[]
- foo ist ein Array von (Array von 8 (Zeiger auf (Zeiger auf (Rückgabe der Funktion) (Zeiger auf (Array von (Zeiger auf char))))))Nun endlich Dekodierung für die in der Frage gegebene Erklärung
float * (*(*foo())[SIZE][SIZE])()
- foo gibt die Funktion zurück (Zeiger auf (Array von SIZE (Array von SIZE) (Zeiger auf (Funktion gibt Zeiger auf float zurück)))Das Folgende ist der Link für den Artikel, aus dem ich diesen Dekodierungsprozess gelesen habe
Beispiel 10 wurde diesem Artikel entnommen
http://www.unixwiz.net/techtips/reading-cdecl.html
quelle
von http://cdecl.org/
Deklarieren Sie foo als Funktionsrückgabezeiger auf Array. GRÖSSE des Arrays GRÖSSE des Zeigers auf Funktionsrückgabezeiger auf Float
quelle