2012-11-06 11 views
15

Sono abbastanza nuovo per C, e sto cercando di capire alcune dichiarazioni C. Qualcuno può aiutarmi a spiegare il significato di queste dichiarazioni C?Calcolo delle dichiarazioni C

double (*b)[n]; 
double (*c[n])(); 
double (*d())[n]; 

Apprezzo l'aiuto!

+8

Go [spirale ....] (http://c-faq.com/decl/spiral.anderson.html) –

+1

Tale nesso è in realtà molto utile, grazie! –

+0

+1 per averlo chiesto Ho avuto la stessa domanda quando stavo esaminando il codice del kernel –

risposta

12
double (*b)[n]; 

b è un puntatore a un array di n raddoppia

double (*c[n])(); 

c è un array di n puntatori a funzioni tenendo numero imprecisato di argomenti e di ritorno doppio

double (*d())[n]; 

d è una funzione che accetta un numero non specificato di argomenti e restituisce un puntatore a un array di n double

In generale, per analizzare questo tipo di dichiarazioni nella propria testa, adottare il seguente approccio. Vediamo l'ultima dichiarazione, ad esempio

double (*d())[n]; 

qual è la prima cosa che viene fatto per d? Si chiama con(), quindi è una funzione che richiede un numero non specificato di argomenti e returnig ... qual è il risultato? È dereferenziato (*), pertanto è un puntatore a. Il risultato viene quindi indicizzato, quindi è un array di n ... cosa rimane? una doppia, quindi di doppia. Leggendo le parti in grassetto, avrai la tua risposta.

Vediamo un altro esempio

void (*(*f)(int)[n])(char) 

Qui, f è prima Dereferenced, quindi è un puntatore ad ... è quindi chiamato con (int), quindi una funzione di presa int e il ritorno, il risultato viene quindi indicizzato con [n], quindi un array di n. Il risultato è nuovamente dereferenziato, quindi i puntatori a. Quindi il risultato è chiamato da (char), quindi le funzioni assumono il carattere e il reso (tutto è vuoto è vuoto) vuoto. Quindi f è un puntatore a una funzione che assume int e restituisce una matrice di n puntatori a funzioni che accettano char e return void.

HTH

+0

@Joachim: Ah, ho dimenticato che era C. Fisso –

+0

Grazie, la spiegazione alla fine mi ha aiutato a capire meglio questo! –

+0

@JoeCrawley: aggiunto un altro esempio ... più complicato. –

8

La regola di base per analizzare le dichiarazioni C è "leggere da destra a sinistra e verso l'esterno il salto verso destra quando si lascia un paio di parentesi", cioè avviare la la coppia più profondamente annidata di parentesi e poi lavoraci guardando verso destra. Tecnicamente devi conoscere l'associatività dell'operatore, ma funziona abbastanza bene nella maggior parte delle situazioni.

Ora lascia applicare questa regola (semplificato) alla tua domanda:


double (*b)[n]; 
     ^

b è un puntatore

double (*b)[n]; 
     ^

a

double (*b)[n]; 
      ^^^ 

e matrice

double (*b)[n]; 
^^^^^^ 

dei doppi.


double (*c[n])(); 
     ^^^^ 

c è un array di

double (*c[n])(); 
     ^

puntatori a

double (*c[n])(); 
       ^^ 

funzioni

double (*c[n])(); 
^^^^^^ 

ritorno doppia.


double (*d())[n]; 
     ^^^ 

d è una funzione

double (*d())[n]; 
     ^

restituendo un puntatore a

double (*d())[n]; 
      ^^^ 

una serie di

double (*d())[n]; 
^^^^^^ 

doppie


C'è un programma di utilità pulito trovato sulla maggior parte dei sistemi * nix, chiamato cdecl, che prende una stringa di dichiarazione di C e lo trasforma in una frase in linguaggio naturale.

1

Ci sono due grandi risorse per capire "C senza senso":

uscita di cdecl.org:

  • double (*c[n])(): Errore di sintassi (n non è valido qui)
  • double (*c[])(): dichiarare c come array di puntatore a funzione che restituisce doppia
3

Let provare questo modo.

prima, è necessario avere familiarità con questi tre simboli:

1. * -- a pointer. 
2. [] -- an array. 
3.() -- a function.(notice: not parentheses)

prendiamo "doppio (* d()) [n]" come esempio.

il primo passo è trovare l'identificatore nella dichiarazione, un identificatore è il nome della variabile, qui è "d".

(i) 
-- what is "d"? 
------------------------------------------------------------------------ 
look to the right side of the identifier, to see if there is a "[]" or a "()" : 
...d[]...: d is an array. 
...d()...: d is a function. 

if neither, look to the left side, to see if there is a "*" : 
...*d...: d is a pointer. 
------------------------------------------------------------------------

ora abbiamo trovato che d è una funzione. uso x per sostituire d(), allora la dichiarazione diventa "double (* x) [n]"

(ii) 
-- what is "x"? 
------------------------------------------------------------------------ 
repeat (i), we find that x is a pointer. 
that means, d is a function returning a pointer. 
------------------------------------------------------------------------

uso y per sostituire * x, allora la dichiarazione diventa "double y [n]"

(iii) 
-- what is "y"? 
------------------------------------------------------------------------ 
repeat (i), we find that y is an array of n elements. 
that means, d is a function returning a pointer to an array of n elements. 
------------------------------------------------------------------------

uso z per sostituire y [n], allora la dichiarazione diventa "double z"

(iv) 
-- what is "z"? 
------------------------------------------------------------------------ 
repeat (i), we find that z is a double. 
that means, d is a function returning a pointer to an array of n double elements. 
------------------------------------------------------------------------

vediamo un'altra espressione:

void (*(*f)(int)[n])(char)
1. 
    we find f. 
2. 
    f is a pointer. *f -> a 
    void (*a(int)[n])(char) 
3. 
    a is a function. a() -> b 
    void (*b[n])(char) 
    --f is a pointer to a function (with an int parameter)-- 
4. 
    b is an array. b[] -> c 
    void (*c)(char) 
    --f is a pointer to a function returning an array (of n elements)-- 
5. 
    c is a pointer. *c -> d 
    void d(char) 
    --f is a pointer to a function returning an array of n pointers-- 
6. 
    d is a function returning void. 
    --f is a pointer to a function returning an array of n pointers to functions (with a char parameter) returning void--