Domanda

Esiste un modo per creare un array di dimensioni doppie con script doppio in C (non C ++, solo C)? So che per creare un array di dimensioni singole con script singolo, basta usare un puntatore, ad esempio

float *array;
array = (float *) calloc(sizeof(float), n);

crea un array singolarmente con script di float di dimensione n. C'è qualcosa di simile che posso fare per gli array doppiamente scritti?

È stato utile?

Soluzione

Non ci sono matrici con doppio script in C; ci sono solo matrici di matrici. Per esempio. in questo modo:

int a[3][3];

Dovrebbe essere letto come "array di 3 array di 3 pollici", non come "array di 3x3 pollici". Ciò è immediatamente visibile dai tipi di espressioni - ad es. a [0] è un'espressione valida e il suo tipo è int [3] .

Per i tipi di array, la dimensione dell'array fa parte del tipo e pertanto deve essere nota al momento della compilazione. Pertanto, mentre puoi avere un tipo " puntatore agli array " per rendere dinamica una dimensione, le restanti dovrebbero ancora essere riparate:

int (*p)[3] // pointer to arrays of 3 ints each

Esistono due soluzioni alternative tradizionali:

  1. Usa semplicemente un array dinamico monodimensionale di elementi larghezza x altezza e calcola gli indici 1D da coordinate 2D come (y * larghezza + x) te stesso

  2. Usa il puntatore ai puntatori:

    int** a = malloc(sizeof(int*) * height);
    for (i = 0; i < height; ++i) a[i] = malloc(sizeof(int) * width);
    a[0][0] = 123;
    ...
    

    Il problema qui è che il tuo array non deve più essere rettangolare e non puoi davvero applicarlo. Per quanto riguarda le prestazioni, è anche peggio di un singolo blocco contiguo di memoria.

In C99, puoi anche usare matrici di lunghezza variabile:

void foo(int width, int height) {
    int a[width][height];
    ...
}

Altri suggerimenti

Le comp.lang.c FAQ ha una buona sezione in merito.

Puoi fare quasi la stessa cosa per array multidimensionali.

float **array;
array = calloc(sizeof(float*), n);
for(int i = 0; i < n; i++)
{
    array[i] = calloc(sizeof(float), n);
}

Se vuoi una matrice con n righe e m colonne, puoi usare un array lineare di lunghezza m * n per rappresentare questo, dove ogni indice i rappresenta

row = i  / n
col = i  % n

e la mappatura inversa

i  = row * n  + col

La maggior parte dei pacchetti di algebra che usano matrici come matlab in realtà usano questa rappresentazione, perché si generalizza bene a qualsiasi dimensione (si potrebbe generalizzare anche questa a una matrice tridimensionale).

No, non è possibile. In alternativa, allocare un singolo array e definire una funzione di indicizzazione che prende le coordinate e restituisce un indice nell'array.

int Index(int i, int j, int numCols)
{ 
    return i * numCols + j;
}

int numRows = 100;
int numCols = 200;

float *data = malloc(sizeof(float) * numRows * numCols);

data[Index(34, 56, numCols)] = 42.0f;

Puoi usare array di lunghezza variabile C99 (funziona con gcc):

#include <stdio.h>
#include <stdlib.h>

void foo(size_t rows, size_t cols, float array[rows][cols])
{
    printf("%f\n", array[2][3]);
}

int main(void)
{
    size_t rows = 4;
    size_t cols = 5;
    float (*array)[cols] = calloc(sizeof (float), rows * cols);
    array[2][3] = 42;
    foo(rows, cols, array);
}

Sono sorpreso che nessuno abbia sottolineato l'alternativa "ovvia" che preserva la singola allocazione contigua per la matrice principale, ma ha il vettore di puntatori per fornire un doppio abbonamento. (Suppongo che ciò significhi che non è ovvio, dopo tutto.)

float **array2d = malloc(sizeof(*array2d) * height);
float  *array1d = malloc(sizeof(*array1d) * height * width);

for (i = 0; i < height; ++i)
    array2d[i] = &array1d[i * width];

Ora puoi scrivere accessi in array 2D come al solito:

array2d[0][0] = 123.0;

Chiaramente, dobbiamo anche controllare l'allocazione della memoria.

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