2013-10-14 2 views
16

Mi chiedevo come funzionano gli array in c. Finisco con un'ipotesi e mi piacerebbe sapere se ho ragione o no.come funzionano gli array internamente in c/C++

Sappiamo che gli array sono una sequenza di casi di memoria adiacenti (riquadri), in cui ogni casella ha le dimensioni del tipo che immagazzina (vale a dire se una casella INT ha una dimensione = sizeof (int) e una matrice di 3 INT richiede in memoria posti adiacenti di 3 sizeof (int))

Ora sappiamo anche che possiamo allocare dinamicamente memoria per un array di un certo tipo (malloc in C, nuovo in C++).

ciò che mi meraviglia è il fatto che un array abbia per origine l'indirizzo della prima casella dell'array e il primo valore (il valore nella casella successiva) quando lo si chiama con la parentesi [0] è array [0] == * (array + 0) == * array (se l'array è stato dichiarato "tipo * array" o "tipo array []" o "tipo array [dimensione]") e "array" chiamato in questo modo se definire come un puntatore o un array ("tipo * array" o "tipo array []" o "tipo array [dimensioni]") è l'indirizzo della prima casella.

Finisco per pensare e mi piacerebbe una conferma su questo: gli array quando anche dichiarati con le parentesi quadre ([]) sono effettivamente in memoria una sequenza di n puntatori contenenti ciascuno (avendo come valore non un indirizzo) l'indirizzo di una casella di memoria Bi contenente il valore effettivo + quelle caselle di memoria (B0, ..., ognuna contenente i valori effettivi). tale che nel e quando si dichiara "int array [5]" il programma alloca effettivamente 5 caselle adiacenti di puntatori int P0, P1, .., P4 e 5 posti di memoria di dimensione int sparsi in tutta la memoria del computer B0, B1 ,. .., B4 in cui il valore di Pi è l'indirizzo del Bi

enter image description here

ho ragione o torto !! ?? Grazie!

+6

No, l'array ha gli interi effettivi a meno che non si abbia un 'int * arr []'. – chris

+2

+1 per immagine :) –

+1

Leggere la sezione 6 delle [domande frequenti su comp.lang.c (http://www.c-faq.com/). –

risposta

7

array quando anche dichiarato con le parentesi quadre ([]) sono in realtà in memoria una sequenza di n puntatori ciascuna contenente [...] l'indirizzo di una casella di memoria Bi contenente la tali caselle memoria

valore effettivo +

No.

Sembra che tu sia perplesso su come array[0] == *(array+0) == *array possa essere vero sia per un array dichiarato come int array[10]; e int *array = ...;. Una domanda perfettamente ragionevole; Ci viene detto che per un puntatore ptr l'espressione *ptr ottiene il valore puntato dal puntatore, quindi quando usiamo la stessa sintassi con un array dove sono gli indirizzi che stiamo dereferenziando?

Ecco il segreto: l'operatore indice di array ([]) non funziona sugli array in C e C++.Quando lo si applica a un array, la lingua converte implicitamente l'array in un puntatore al primo elemento dell'array. Quindi, aggiungendo a un array o al dereferenziamento, un array sembra comportarsi come aggiungere o dereferenziare un puntatore.

int array[10]; 

// These lines do exactly the same thing: 
int *ptr1 = &array[0]; // explicitly get address of first element 
int *ptr2 = array;  // implicitly get address of first element 

Così array sono davvero un insieme contiguo di elementi in memoria in cui ogni elemento è in realtà il valore, non un puntatore ad un'altra posizione contenente il valore. È solo che il modo in cui gli array sono definiti significa che spesso convertono implicitamente in un puntatore e quindi sembra che ci siano dei puntatori quando in realtà c'è solo una conversione implicita.

+0

"L'operatore indice della matrice ([]) non funziona sugli array." Certo che lo fa. Ecco a cosa serve Ma ciò che l'operatore * fa * è identico all'aggiunta del puntatore. – EJP

+4

@EJP No, se leggi le specifiche C++ vedrai che l'operatore pedice è definito solo per lavorare con espressioni di tipo "puntatore a T", non espressioni con tipi di array. Il motivo per cui l'uso di un indice su un array è identico al suo utilizzo su un puntatore è perché usarlo su un array converte prima l'array in un puntatore e dopo di ciò è effettivamente identico. – bames53

+0

@EJP Un altro modo per vedere questo è se si utilizza la funzione di dump AST in clang sul codice come: 'int main() {int array [10]; array [0]; } ', l'AST mostrerà un nodo' ArraySubscriptExpr' che ha un nodo 'ImplicitCastExpr ' sulla sinistra. – bames53

0

Pensate a come questo:

array[n] è semplicemente uno zucchero sintattico per *(array + n).

E no, non ci sono puntatori, la matrice contiene effettivamente i valori in un intervallo di memoria continuo.

+0

sì, questo è quello che ho scritto e come lo capisco, ma la mia domanda è cosa succede in termini di allocazione di memoria quando si fa "int array [n]" (o qualsiasi altro tipo per quella materia)? –

+1

'*' esegue il dereferenziamento, quindi ottieni * il valore * dalla posizione 'n'. se ciò che hai scritto fosse vero, ci sarebbe bisogno di un ulteriore passo per il dereferenziamento. (ma non c'è come si può vedere chiaramente dalla notazione). –

+1

vedi la parte verde della tua foto? scrivi i valori direttamente lì. questo è quello che succede. l'allocazione effettiva dipende dal fatto che si tratti di una variabile locale o di una allocata dinamicamente. ognuna ha le sue regole (specifiche dell'implementazione) * ma * non è specifica dell'array. –

2

Gli array sono memorizzati in modo contiguo nella memoria virtuale. Tuttavia, gli indirizzi di memoria fisica a cui mappano potrebbero o potrebbero non essere contigui.

E gli elementi della matrice non memorizzano un puntatore per puntare all'elemento successivo. Solo il valore è memorizzato.