Dichiarazioni complesse

Come interpreto dichiarazioni complesse come:

int * (* (*fp1) (int) ) [10]; ---> declaration 1 int *( *( *[5])())(); --------> declaration 2 

C’è qualche regola da seguire per capire le dichiarazioni di cui sopra?

Ecco un ottimo articolo su come leggere dichiarazioni complesse in C: http://www.codeproject.com/KB/cpp/complex_declarations.aspx

Mi ha aiutato molto!

Soprattutto, dovresti leggere la sezione “La regola giusta”. Qui citazione:

int * (* (* fp1) (int)) [10]; Questo può essere interpretato come segue:

  1. Inizia dal nome della variabile ————————– fp1
  2. Niente a destra ma) quindi vai a sinistra per trovare * ————– è un puntatore
  3. Salta da parentesi e incontra (int) ——— a una funzione che accetta un int come argomento
  4. Vai a sinistra, trova * —————————————- e restituisce un puntatore
  5. Salta tra parentesi, vai a destra e premi [10] ——– su un array di 10
  6. Vai a sinistra cerca * —————————————– Puntatori a
  7. Vai di nuovo a sinistra, trova int ——————————– ints.

Puoi usare cdecl * :

 cdecl> explain int *( *( *a[5])())(); declare a as array 5 of pointer to function returning pointer to function returning pointer to int cdecl> explain int * (* (*fp1) (int) ) [10]; declare fp1 as pointer to function (int) returning pointer to array 10 of pointer to int 

* Collegato è un sito Web che utilizza questo strumento da riga di comando nel back-end.

Ho imparato il seguente metodo molto tempo fa:

Inizia dall’identificatore del tipo (o dalla parentesi interna) e muovi seguendo una spirale prendendo prima l’elemento a destra

In caso di

  int * (* (*fp1) (int) ) [10]; 

Si può dire:

  • fp1 è un (niente a destra quindi spostati a sinistra)
  • puntatore a (sposta fuori dalla parentesi interna
  • una funzione che assume int come agument (il primo a destra)
  • e restituisce un puntatore a (esci da parentesi)
  • una matrice di 10 elementi di tipo
  • puntatore a (niente lasciato a destra)
  • int

Con il risultato di:

fp1 è un puntatore a una funzione che accetta un int e restituisce un puntatore a un array di 10 puntatori a int

Disegnare la spirale reale (almeno nella tua mente) aiuta molto.

Per risolvere queste dichiarazioni complicate, la regola da tenere a mente è che la precedenza dell’operatore di chiamata di funzione () e dell’operatore di indice di matrice [] è maggiore dell’operatore di dereferenziazione *. Ovviamente, è ansible utilizzare la parentesi () per sovrascrivere queste precedenze.

Ora, calcola la tua dichiarazione dal centro, che significa dal nome dell’identificatore.

int * (* (* fp1) (int)) [10]; —> dichiarazione 1

In base alla regola delle precedenze sopra menzionata, puoi facilmente capirlo suddividendo la dichiarazione come

fp1 * (int) * [10] * int

e leggerlo direttamente da sinistra a destra in inglese come “fp1 è un puntatore a una funzione che accetta un int e restituisce un puntatore a un array [10] di puntatori a int”. Nota che la dichiarazione è rotta in questo modo solo per aiutare a capirlo manualmente. Il compilatore NON ha bisogno di analizzarlo in questo modo.

Allo stesso modo,

int * (* (* [5]) ()) (); ——–> dichiarazione 2

è rotto come

[5] * () * () * int

Quindi, dichiara “un array [5] di puntatori di tipo a function () che restituisce un puntatore a una funzione () che a sua volta restituisce un puntatore a int”.

Anche se è già stata data una risposta, ma si può anche leggere questo articolo:

http://unixwiz.net/techtips/reading-cdecl.html

Inizia con l’identificatore più a sinistra e cerca di uscire, ricordando che è assente qualsiasi raggruppamento esplicito [] e () prima di * , ad esempio:

     * a [] - è una matrice di puntatore
   (* a) [] - è un puntatore a un array
     * f () - è una funzione che restituisce un puntatore
   (* f) () - è un puntatore a una funzione

Pertanto, leggiamo int *(*(*fp1)(int))[10] come:

  fp1 -- fp1 *fp1 -- is a pointer (*fp1)(int) -- to a function taking an int parameter *(*fp1)(int) -- returning a pointer (*(*fp1)(int))[10] -- to a 10-element array *(*(*fp1)(int))[10] -- of pointer int *(*(*fp1)(int))[10] -- to int 

La dichiarazione int *(*(*[5])())() presenta un po ‘di difficoltà in quanto non esiste un identificatore; in genere lo si vede nelle dichiarazioni di funzione in cui un parametro è di quel tipo:

 void foo(int *(*(*[5])())(), double); 

È lo stesso principio del parametro int non denominato nella dichiarazione di fp1 . L’array ci dà l’indizio, puoi anche cercare il gruppo interno più a sinistra delle parentesi.

  -- unnamed [5] -- is a 5-element array ([] binds before *) *[5] -- of pointers (*[5])() -- to functions *(*[5])() -- returning pointers (*(*[5])())() -- to functions *(*(*[5])())() -- returning pointers int *(*(*[5])())() -- to int 

La spirale in senso orario:

 * http://c-faq.com/decl/spiral.anderson.html