Un puntatore e una serie sono cose diverse. Un puntatore a un tipo contiene l'indirizzo in cui è allocata una variabile di tipo dichiarato.
Un array di un tipo è uno spazio di memoria in cui le variabili del tipo dichiarato sono memorizzate in modo contiguo.
Ora sei una dichiarazione. Non c'è alcuna ambiguità (anche se non è così evidente) nelle dichiarazioni C. In caso Un voi hanno dichiarato:
int **M1;
Questo non è un array 2D, nemmeno uno monodimensionale. Stai dichiarando una variabile, M!
, come puntatore a un altro puntatore a un int. Nella parola piano M1
verrà trattenuto l'indirizzo di un'altra variabile che a sua volta contiene l'indirizzo di cui nella memoria è memorizzato un numero intero. Now executing:
M1 = (int **)malloc(m * sizeof(int *));
assegnato al M1
l'indirizzo un'area di memoria che può memorizzare fino a m contigui puntatori interi, un accesso alla memoria puntata da M1
, e successive riprese agisce come accesso matrice (ma non lo è).Questo è più o meno equivalente alla dichiarazione statico:
int *[m]; //an array of pointers to int
Poi assegnando ogni elemento di questo pseudo-array di memoria per d
interi contigui:
for (int i=0; i<m; i++)
{
M1[i] = (int *)malloc(d * sizeof(int));
}
ora hanno spazio per memorizzare d
consecutivo numeri interi che iniziano agli indirizzi salvati in M1[i]
per i = 0-> d-1.
Cosa succede quando si tenta di accedere a un valore utilizzando gli indici: M1[a][b]
? Il compilatore recupera l'indirizzo indicato da M1
e utilizza il primo indice (a
), recupera il contenuto indicato dall'indirizzo nella posizione atht dell'array di puntatori. Questo punta al primo intero del sottospazio che abbiamo assegnato per contenere d
int consecutive. Questo è davvero un array monodimensionale di int. Applicando il secondo pedice ad esso il compilatore recupera finalmente il numero intero richiesto. Cose a un array bidimensionale che si rivolge, ma senza banana! Non è una matrice bidimensionale di int. :-)
In caso B si dichiara un puntatore a un array monodimensionale di int, a cui si stanno assegnando spazio sufficiente per contenere l'array bidimensionale. Perché in C non esiste il concetto di matrice multidimensionale, tuttavia il principio di base della serie di array di matrice .... ecc (ad libitum), la dichiarazione:
int (*M1)[m] = malloc(sizeof(int[m][d]));
come un puntatore a modimensiional array con spazio allocato per un array di elementi [m][d]
ha fatto il trucco.
Ma ovviamente entrambe le soluzioni sono sbagliate!
Si stanno utilizzando gli effetti collaterali per ottenere ciò che si desidera, ma utilizzando i surrogati di ciò che si è dichiarato necessario: una matrice bidimensionale di int.
La soluzione corretta è quella di definire un puntatore a una matrice bidimensionale di interi in cui è richiesto solo il primo pedice:
int (*M1)[][m]; //declare a pointer to a real array
M1 = malloc(m * d * sizeof(int)); //Allocate room for bidimensional array
for (int i=0; i<m; i++)
for (int j=0; j<d; j++)
{
(*M1)[i][j] = (i*100)+j; //Fill elements with something using bidimensional subscripting
}
for (int i=0; i<m; i++)
for (int j=0; j<d; j++)
{
printf("[%d][%d]=%d\n", i, j, (*M1)[i][j]); //Check back data...
}
Ora uno sguardo a quello che succede se si va fuori dai limiti nel 3 casi. In caso Un se si ottiene fuori limite con il primo indice potrai raccogliere un puntatore sbagliato che causerà immediatamente colpa di una memoria, nel caso in cui B si avrà colpa di memoria solo se si va fuori di processo memoria indirizzabile, uguale per la soluzione corretta. Questo dovrebbe rispondere alla tua domanda.
scorso, perché stiamo parlando di circa misunderstandigs vettori e puntatori, non fraintendere alla norma ISO 9899: 2011§6.7.6.3/7 che dice:
Una dichiarazione di un parametro come '' l'array di tipo '' deve essere regolato su '' puntatore qualificato per digitare '', dove i qualificatori di tipo (se presenti) sono quelli specificati all'interno di [e] della derivazione del tipo di matrice.Se la parola chiave static appare anche all'interno [e] della derivazione del tipo array , quindi per ogni chiamata alla funzione, il valore dell'argomento effettivo corrispondente di deve fornire l'accesso al primo elemento di un array con almeno molti elementi specificati dall'espressione di dimensione .
che prevede soltanto che array saranno trasmessi soltanto con riferimento (regolata automaticamente dal compilatore), non per valore (cioè legale per le strutture esempio). Non ti viene richiesto di fornire alcun puntatore qualificato invece di un array nella chiamata di funzione o il programma si blocca (Una dichiarazione di un parametro come '' array di tipo '' deve essere regolata su '' puntatore qualificato per digitare '' - significa che verrà regolato dal compilatore, non da te). I casi come char *[]
e char **
funzionano per il motivo sopra riportato, non perché sia legale scambiarli!
Il codice A funziona perfettamente per me. Qual è il tuo ambiente? – blue112
Dove si ottiene esattamente l'errore di segmentazione? –
[Si prega di non trasmettere il risultato di 'malloc()'] (http://stackoverflow.com/a/605858/3233393). – Quentin