Ho ascoltato informazioni contrastanti da fonti diverse e non sono sicuro di quale credere. Come tale, posterò ciò che capisco e chiedo correzioni. Diciamo che voglio usare una matrice 2D. Ci sono tre modi in cui posso farlo (almeno che io sappia).
1 :
int i;
char **matrix;
matrix = malloc(50 * sizeof(char *));
for(i = 0; i < 50; i++)
matrix[i] = malloc(50);
2 :
int i;
int rowSize = 50;
int pointerSize = 50 * sizeof(char *);
int dataSize = 50 * 50;
char **matrix;
matrix = malloc(dataSize + pointerSize);
char *pData = matrix + pointerSize - rowSize;
for(i = 0; i < 50; i++) {
pData += rowSize;
matrix[i] = pData;
}
3 :
//instead of accessing matrix[i][j] here, we would access matrix[i * 50 + j]
char *matrix = malloc(50 * 50);
In termini di utilizzo della memoria, la mia comprensione è che 3 è il più efficiente, 2 è il prossimo, e 1 è il meno efficiente, per i motivi seguenti:
3 : c'è solo un puntatore e un'allocazione e, quindi, un sovraccarico minimo.
2 : Ancora una volta, c'è solo un'allocazione, ma ora ci sono 51 puntatori. Ciò significa che c'è 50 * sizeof(char *)
di overhead in più.
1 : ci sono 51 allocazioni e 51 puntatori, che causano il maggior overhead di tutte le opzioni.
In termini di prestazioni, ancora una volta mi rendo conto che 3 è il più efficiente, 2 è il prossimo, e 1 è il meno efficiente . Motivi:
3 : è necessario un solo accesso alla memoria. Dovremo fare una moltiplicazione e un'aggiunta rispetto a due aggiunte (come nel caso di un puntatore a un puntatore), ma l'accesso alla memoria è abbastanza lento da non avere importanza.
2 : abbiamo bisogno di due accessi alla memoria; una volta per ottenere un char *
, quindi l'appropriato char
. Qui vengono eseguite solo due aggiunte (una volta per ottenere il puntatore char *
corretto dalla posizione di memoria originale e una volta per ottenere la variabile char
corretta da dove char *
punta a), quindi la moltiplicazione (che è più lenta di aggiunta) non è richiesto. Tuttavia, su CPU moderne, la moltiplicazione è più veloce dell'accesso alla memoria, quindi questo punto è mootico.
1 : gli stessi problemi di 2 , ma ora la memoria non è contigua. Ciò causa errori di cache e ricerche extra di tabelle di pagina, rendendolo il meno efficiente del lotto.
Prima di tutto: è corretto? Secondo: c'è un'opzione 4 che mi manca che sarebbe ancora più efficiente?