Ecco la lingua esatta dallo standard C (n1256):
6.3.2.1 lvalue, array e designatori funzione
...
3 Tranne quando è l'operando della
sizeof
operatore o l'unario operatore
&
o è un valore letterale stringa utilizzato per inizializzare un array, un'espressione con tipo '' array di
tipo '' viene convertita in un'espressione con tipo '' puntatore su
tipo ’Che punti all'elemento iniziale dell'oggetto matrice e non è un lvalue. Se l'oggetto array ha una classe di archiviazione di registro, il comportamento non è definito.
La cosa importante da ricordare è che c'è una differenza tra un oggetto (in termini di C, che significa qualcosa che occupa memoria) e l'espressione usato per riferirsi a tale oggetto.
Quando si dichiara una matrice come
int a[10];
l'oggetto designato dal espressionea
è una matrice (cioè, un blocco contiguo di memoria abbastanza grande da contenere 10 valori int
e il tipo di espressione a è "matrice 10 elementi di int
" o int [10]
. Se l'espressione a
viene visualizzata in un contesto diverso da quello degli operandi degli operatori sizeof
o &
, il suo tipo viene convertito implicitamente in int *
e il suo valore è l'indirizzo del primo elemento.
Nel caso dell'operatore sizeof
, se l'operando è un'espressione di tipo T [N]
, allora il risultato è il numero di byte nell'oggetto matrice, non in un puntatore a tale oggetto: N * sizeof T
.
Nel caso dell'operatore &
, il valore è l'indirizzo della matrice, che è la stessa come l'indirizzo del primo elemento della matrice, ma il tipo dell'espressione è differente: data la dichiarazione T a[N];
, il tipo di espressione &a
è T (*)[N]
o puntatore all'array di elementi N di T. Il valore è lo stesso di a
o &a[0]
(l'indirizzo dell'array è uguale all'indirizzo del primo elemento nel array), ma la differenza nei tipi è importante. Ad esempio, dato il codice
int a[10];
int *p = a;
int (*ap)[10] = &a;
printf("p = %p, ap = %p\n", (void *) p, (void *) ap);
p++;
ap++;
printf("p = %p, ap = %p\n", (void *) p, (void *) ap);
vedrete uscita dell'ordine di
p = 0xbff11e58, ap = 0xbff11e58
p = 0xbff11e5c, ap = 0xbff11e80
IOW, avanzando p
aggiunge sizeof int
(4) al valore originale, mentre avanzando ap
aggiunge 10 * sizeof int
(40).
Più linguaggio standard:
6.5.2.1 Array indicizzazione di
Vincoli
1 Una delle espressioni avranno tipo '' puntatore a oggetto
tipo '', l'altra espressione deve avere il tipo intero e il risultato ha tipo ''
tipo ''.
semantica
2 un'espressione postfissa seguita da un'espressione tra parentesi quadre
[]
è una designazione subscripted di un elemento di un oggetto array. La definizione dell'operatore di pedice
[]
è che
E1[E2]
è identico a
(*((E1)+(E2)))
. A causa delle regole di conversione applicabili all'operatore
+
binario, se
E1
è un oggetto array (equivalentemente, un puntatore all'elemento iniziale di un oggetto matrice) e
E2
è un numero intero,
E1[E2]
indica l'elemento
E2
-th di
E1
(conteggio da zero).
Così, quando si pedice un'espressione di matrice, ciò che accade sotto il cofano è che l'offset dall'indirizzo del primo elemento dell'array è calcolato e il risultato è dereferenziato.L'espressione
a[i] = 10;
equivale a
*((a)+(i)) = 10;
che equivale a
*((i)+(a)) = 10;
che equivale a
i[a] = 10;
Sì, matrice indicizzazione di in C è commutativo; per amore di Dio, non farlo mai nel codice di produzione.
Dal gamma subscripting è definito in termini di operazioni di puntatore, è possibile applicare l'operatore pedice alle espressioni di tipo puntatore così come tipo di matrice:
int *p = malloc(sizeof *p * 10);
int i;
for (i = 0; i < 10; i++)
p[i] = some_initial_value();
Ecco una tabella utile per ricordare alcuni di questi concetti:
Declaration: T a[N];
Expression Type Converts to Value
---------- ---- ------------ -----
a T [N] T * Address of the first element in a;
identical to writing &a[0]
&a T (*)[N] Address of the array; value is the same
as above, but the type is different
sizeof a size_t Number of bytes contained in the array
object (N * sizeof T)
*a T Value at a[0]
a[i] T Value at a[i]
&a[i] T * Address of a[i]
Declaration: T a[N][M];
Expression Type Converts to Value
---------- ---- ------------ -----
a T [N][M] T (*)[M] Address of the first subarray (&a[0])
&a T (*)[N][M] Address of the array (same value as
above, but different type)
sizeof a size_t Number of bytes contained in the
array object (N * M * sizeof T)
*a T [M] T * Value of a[0], which is the address
of the first element of the first subarray
(same as &a[0][0])
a[i] T [M] T * Value of a[i], which is the address
of the first element of the i'th subarray
&a[i] T (*)[M] Address of the i-th subarray; same value as
above, but different type
sizeof a[i] size_t Number of bytes contained in the i'th subarray
object (M * sizeof T)
*a[i] T Value of the first element of the i'th
subarray (a[i][0])
a[i][j] T Value at a[i][j]
&a[i][j] T * Address of a[i][j]
Declaration: T a[N][M][O];
Expression Type Converts to
---------- ---- -----------
a T [N][M][O] T (*)[M][O]
&a T (*)[N][M][O]
*a T [M][O] T (*)[O]
a[i] T [M][O] T (*)[O]
&a[i] T (*)[M][O]
*a[i] T [O] T *
a[i][j] T [O] T *
&a[i][j] T (*)[O]
*a[i][j] T
a[i][j][k] T
Da qui, il modello per gli array di dimensioni superiori deve essere chiaro.
Quindi, in breve: gli array non sono puntatori. Nella maggior parte dei contesti, le espressioni dell'array vengono convertite in tipi di puntatore.
possibile duplicato di una domanda dal C++ del sito - faq: [Il nome dell'array è un puntatore in C?] (Http://stackoverflow.com/questions/1641957/is-array-name-a-pointer-in- c) –