Domanda

Sto cercando di implementare le matrici 3D contigue allocati dinamicamente in un codice C. Gli array devono essere contigui perché sto contando su uscita netCDF degli array. Ora ho adattato una soluzione postato qui Stack Overflow Soluzione . Questo funziona bene per l'allocazione dinamica delle matrici e indicizzazione ... tuttavia, quando netCDF li emette v'è un offset che sembra scala della dimensione dell'indice 2a (jcount). Ecco la funzione modificata:

void*** newarray(int icount, int jcount, int kcount, int type_size)
{
  int i,j,k;
  void*** iret = (void***)malloc(icount*sizeof(void***)+icount*jcount*sizeof(void**)+icount*jcount*kcount*type_size);
  void** jret = (void**)(iret+icount);
  char* kret = (char*)(jret+icount*jcount);
  for(i=0;i<icount;i++)
  {
    iret[i] = &jret[i*jcount];
  }
  for(i=0;i<icount;i++)
  {
    for(j=0;j<jcount;j++)
    {
      jret[i*jcount+j] = &kret[i*jcount*kcount*type_size+j*kcount*type_size];
    }
  }
  return iret;
}

Se ho capito correttamente questa modalità IRET è allocato lo spazio per i puntatori 3D che compongono IRET (primo indice), i 2D puntatori che compongono jret (2 ° indice) e lo spazio per i valori effettivi che compongono kret. Il puntatore jret 2D viene quindi associato con la sezione matrice 2D di iret. Poi lo stesso è fatto per kret. Poi ogni indirizzo di iret è puntato al primo valore di ogni sezione di jret. Poi ogni indirizzo del jret è puntato al primo indirizzo di kret.

Per la cronaca, tutto andava bene con il preprocessore valori definiti lavorando per i miei array. Inoltre, se uso alcune dichiarazioni printf nel codice per controllare i valori numerici delle matrici tutti sembrano per indicizzare correttamente e il codice viene eseguito correttamente, è solo l'uscita sembra essere il risultato di una memoria non contigue degli array.

ho una struttura della forma:

typedef struct
{
  double ***test;
} STRUCT_TYPE;

che ho poi allocare utilizzando

mhd    = (STRUCT_TYPE *)  malloc(sizeof(STRUCT_TYPE));
mhd.test = (double***) newarray(101,7,101,sizeof(double));

Questo può essere un problema con netCDF ... ma vorrei solo sapere la mia routine di allocazione non è il problema.

È stato utile?

Soluzione

Questo è in realtà una risposta alla domanda nella risposta di Lazer:

  

Questo mi fa pensare che quando C alloca memoria per un array alloca la memoria utilizzata> per memorizzare i valori prima poi alloca la memoria per i puntatori che forniscono   struttura alla matrice multidimensionale.

     

Forse qualcuno può chiarire questo per me?

C'è una differenza molto fondamentale in C tra

double arr[A][B][C];

e

double ***ptr;

Sebbene entrambi possono essere indicizzati con x[i][j][k], il codice macchina risultante è molto diverso.

double arr[A][B][C] è una matrice di un'array di array B di C doppie. Quando indicizzare la nel codice come arr[i][j][k], il compilatore traduce che ad un offset di ((i*B + j)*C + k)*sizeof(double) byte dall'inizio della arr. Non ci sono puntatori intermedi coinvolti qui, ma le dimensioni B e C devono essere noti al compilatore.

'doppia *** ptr' è un puntatore (l'inizio di un array di) puntatori a (l'inizio di un array di) puntatori a (l'inizio di un array di) doppio. Quando indicizzare la nel codice come ptr[i][j][k], il compilatore ha altra scelta che fare ogni operazione di indicizzazione separatamente e seguire tutti i puntatori intermedi. Questo si traduce in un codice simile a

temp1 = ptr[i];
temp2 = temp1[j];
result = temp2[k];

La funzione intaglia newarray tutti questi elementi per-array su un unico blocco di memoria, ma che non è richiesto dalla lingua e il compilatore non avere la conoscenza che ciò avviene, quindi deve trattare tutta la componente -arrays come completamente indipendenti l'una dall'altra.

Altri suggerimenti

Beh ho trovato un fix ... anche se è più di una cosa convenzione. Quando ho Originariamente progettato il mio codice ho semplicemente usato una direttiva del preprocessore per dichiarare il mio dimensioni array. Poi ho semplicemente dichiarato ogni matrice all'interno della struttura. Al fine di salvare la memoria ho semplicemente passato un puntatore alle strutture ai miei sub-funzioni. Questo significava se stavo per fare riferimento a un elemento al di fuori della routine main () ho usato qualcosa come:

grid->x;

Ora e mi fa riferimento a ogni elemento di x come

grid->x[i][j][k];

Naturalmente, quando una funzione netCDF aveva bisogno di un puntatore alla variabile che stava per negozio, ho appena passato che

grid->x

Tuttavia, utilizzando questa nuova funzione di allocazione della memoria, quando passo a un funzione di realtà sto passando il primo indirizzo del set di spazio di memoria da parte per i vari puntatori. In sostanza stavo passando un puntatore a un indirizzo sbagliato in memoria. Tutto quello che dovevo fare è cambiare l'argomento passato a:

&grid->x[0][0][0]

e ottengo l'uscita di matrice corretta. Ciò fa pensare che quando C alloca memoria per un array alloca la memoria utilizzata per memorizzare i valori prima poi alloca la memoria per i puntatori che forniscono la struttura alla matrice multidimensionale.

Forse qualcuno può chiarire questo per me?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top