C Language Interpretazione delle dichiarazioni

Esempio

Una peculiarità sintattica distintiva di C è che le dichiarazioni rispecchiano l'uso dell'oggetto dichiarato come sarebbe in un'espressione normale.

Il seguente insieme di operatori con identica precedenza e associatività viene riutilizzato nei dichiaratori, vale a dire:

  • l'operatore unario * "dereferenziazione" che denota un puntatore;
  • l'operatore binario [] "subscription in array" che denota una matrice;
  • l'operatore (1 + n) -ary () "chiamata di funzione" che denota una funzione;
  • il () raggruppa le parentesi che sovrascrivono la precedenza e l'associatività del resto degli operatori elencati.

I tre operatori precedenti hanno la seguente precedenza e associatività:

Operatore Precedenza relativa Associatività
[] (abbonamento array) 1 Da sinistra a destra
() (chiamata di funzione) 1 Da sinistra a destra
* (dereferenziazione) 2 Da destra a sinistra

Quando si interpretano le dichiarazioni, si deve partire dall'identificatore verso l'esterno e applicare gli operatori adiacenti nell'ordine corretto come nella tabella precedente. Ogni applicazione di un operatore può essere sostituita con le seguenti parole inglesi:

Espressione Interpretazione
thing[X] una serie di dimensioni X di ...
thing(t1, t2, t3) una funzione che prende t1 , t2 , t3 e restituisce ...
*thing un puntatore a ...

Ne consegue che l'inizio dell'interpretazione inglese inizierà sempre con l'identificatore e terminerà con il tipo che si trova sul lato sinistro della dichiarazione.

Esempi

char *names[20];

[] ha la precedenza su * , quindi l'interpretazione è: i names sono una matrice di dimensione 20 di un puntatore a char .

char (*place)[10];

Nel caso in cui si utilizzino le parentesi per sovrascrivere la precedenza, viene applicato prima * : place è un puntatore a una matrice di dimensione 10 di char .

int fn(long, short);

Non c'è alcuna precedenza da preoccupare qui: fn è una funzione che richiede long , short e ritorno int .

int *fn(void);

Il fn () viene applicato per primo: fn è una funzione che prende il void e restituisce un puntatore a int .

int (*fp)(void);

Sovrascrivere la precedenza di () : fp è un puntatore a una funzione che prende il void e che restituisce int .

int arr[5][8];

Gli array multidimensionali non sono un'eccezione alla regola; gli operatori [] sono applicati nell'ordine da sinistra a destra secondo l'associatività nella tabella: arr è una matrice di dimensione 5 di una matrice di dimensione 8 di int .

int **ptr;

I due operatori di dereferenziazione hanno la stessa precedenza, quindi l'associatività ha effetto. Gli operatori sono applicati nell'ordine da destra a sinistra: ptr è un puntatore a un puntatore a un int .

Dichiarazioni multiple

La virgola può essere utilizzata come separatore (* non * che agisce come l'operatore virgola) per delimitare più dichiarazioni all'interno di una singola istruzione. La seguente dichiarazione contiene cinque dichiarazioni:
int fn(void), *ptr, (*fp)(int), arr[10][20], num;

Gli oggetti dichiarati nell'esempio precedente sono:

  • fn : una funzione che si void e restituisce int ;
  • ptr : un puntatore a un int ;
  • fp : un puntatore a una funzione che assume int e restituisce int ;
  • arr : una matrice di dimensione 10 di una matrice di dimensione 20 di int ;
  • num : int .

Interpretazione alternativa

Poiché il mirror delle dichiarazioni viene utilizzato, una dichiarazione può anche essere interpretata in termini di operatori che potrebbero essere applicati sull'oggetto e il tipo risultante finale di tale espressione. Il tipo che si trova sul lato sinistro è il risultato finale che viene restituito dopo l'applicazione di tutti gli operatori.

/*
 * Subscripting "arr" and dereferencing it yields a "char" result.
 * Particularly: *arr[5] is of type "char".
 */
char *arr[20];

/*
 * Calling "fn" yields an "int" result.
 * Particularly: fn('b') is of type "int".
 */
int fn(char);

/*
 * Dereferencing "fp" and then calling it yields an "int" result.
 * Particularly: (*fp)() is of type "int".
 */
int (*fp)(void);

/*
 * Subscripting "strings" twice and dereferencing it yields a "char" result.
 * Particularly: *strings[5][15] is of type "char"
 */
char *strings[10][20];