Domanda

In C, so di poter allocare dinamicamente una matrice bidimensionale sull'heap utilizzando il seguente codice:

int** someNumbers = malloc(arrayRows*sizeof(int*));

for (i = 0; i < arrayRows; i++) {
    someNumbers[i] = malloc(arrayColumns*sizeof(int));
}

Chiaramente, questo crea in realtà un array monodimensionale di puntatori a un gruppo di array monodimensionali separati di numeri interi, e "Il Sistema" può capire cosa intendo quando chiedo:

someNumbers[4][2];

Ma quando dichiaro staticamente una matrice 2D, come nella seguente riga ...:

int someNumbers[ARRAY_ROWS][ARRAY_COLUMNS];

... non una struttura simile ottenere creata in pila, o è di un'altra forma del tutto? (Vale a dire si tratta di una serie 1D di puntatori? Se no, di cosa si tratta, e come riferimenti ad esso vengono capito?)

Inoltre, quando ho detto, "il sistema", ciò che è effettivamente responsabile per capire che fuori? Il nocciolo? O il compilatore C sorta fuori durante la compilazione?

È stato utile?

Soluzione

A statici bidimensionali aspetto matrice come un array di array - è solo disposto contiguo in memoria. Gli array non sono la stessa cosa come puntatori, ma perché spesso è possibile usarli praticamente intercambiabile che può diventare confuso a volte. Il compilatore registra correttamente, però, che rende la linea tutto piacevolmente. Dovete stare attenti con gli array 2D statiche come si parla, dal momento che se si tenta di passare una a una funzione di prendere un parametro int **, cose cattive stanno per accadere. Ecco un rapido esempio:

int array1[3][2] = {{0, 1}, {2, 3}, {4, 5}};

In sguardi di memoria come questo:

0 1 2 3 4 5

esattamente la stessa:

int array2[6] = { 0, 1, 2, 3, 4, 5 };

Ma se si tenta di passare array1 a questa funzione:

void function1(int **a);

si otterrà un messaggio di avviso (e l'applicazione non riuscirà a accedere correttamente l'array):

warning: passing argument 1 of ‘function1’ from incompatible pointer type

Poiché una matrice 2D non è la stessa int **. Il decadimento automatico di una matrice in un puntatore va solo "un livello profondo" per così dire. È necessario dichiarare la funzione come:

void function2(int a[][2]);

o

void function2(int a[3][2]);

Per rendere tutto felice.

Questo stesso concetto si estende a n array -dimensionale. Approfittando di questo tipo di attività divertenti nella vostra applicazione in genere rende solo più difficile da capire, però. Quindi state attenti là fuori.

Altri suggerimenti

La risposta è basata sull'idea che C non lo fa davvero sono 2D array - ha array-di-array. Quando si dichiara questo:

int someNumbers[4][2];

Si stanno chiedendo someNumbers essere un array di 4 elementi, in cui ogni elemento di tale matrice è di tipo int [2] (che è esso stesso un array di 2 ints).

L'altra parte del puzzle è che gli array sono sempre disposti in modo contiguo in memoria. Se chiedete:

sometype_t array[4];

allora che sarà sempre simile a questa:

| sometype_t | sometype_t | sometype_t | sometype_t |

(4 sometype_t oggetti disposti uno accanto all'altro, senza spazi in mezzo). Quindi nel tuo someNumbers array-of-array, sarà simile a questa:

| int [2]    | int [2]    | int [2]    | int [2]    |

E ogni elemento int [2] è di per sé una matrice, che assomiglia a questo:

| int        | int        |

Nel complesso, si ottiene questo:

| int | int  | int | int  | int | int  | int | int  |
unsigned char MultiArray[5][2]={{0,1},{2,3},{4,5},{6,7},{8,9}};

in memoria è pari a:

unsigned char SingleArray[10]={0,1,2,3,4,5,6,7,8,9};

In risposta alla tua anche:. Entrambi, anche se il compilatore sta facendo la maggior parte del lavoro pesante

Nel caso di array allocati staticamente, "sistema" sarà il compilatore. Essa si riserverà la memoria come si farebbe per qualsiasi variabile di stack.

Nel caso della matrice malloc'd, "Il Sistema" sarà il realizzatore di malloc (il kernel di solito). Tutto il compilatore assegnerà è il puntatore base.

Il compilatore sta andando sempre gestire il tipo come quello che sono dichiarati tranne nell'esempio Carl diede dove può capire l'utilizzo intercambiabile. Questo è il motivo per cui se si passa in una [] [] ad una funzione che deve presumere che si tratta di un piatto allocato staticamente, dove ** si presume essere puntatore al puntatore.

Per accedere a una particolare matrice 2D considerare la mappa di memoria di una dichiarazione di matrice come mostrato nel codice seguente:

    0  1
a[0]0  1
a[1]2  3

Per accedere a ciascun elemento, la sua sufficiente passare solo quale matrice ti interessa come parametri della funzione. Quindi utilizzare offset per colonna per accedere a ciascun elemento singolarmente.

int a[2][2] ={{0,1},{2,3}};

void f1(int *ptr);

void f1(int *ptr)
{
    int a=0;
    int b=0;
    a=ptr[0];
    b=ptr[1];
    printf("%d\n",a);
    printf("%d\n",b);
}

int main()
{
   f1(a[0]);
   f1(a[1]);
    return 0;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top