Array bidimensionali (multidimensionali)

di il
8 risposte

Array bidimensionali (multidimensionali)

Ciao a tutti,
chiedo a tutti scusa in anticipo per il post un po' lungo e forse per molti un po' noioso. Ma un vostro contributo, sarebbe davvero utile per migliorare la mia comprensione su determinati argomenti.
Proseguendo nello studio e nell'approfondimento del C è giunto il momento degli array multidimensionali.
Se da una parte i concetti teorici mi sembrano sufficientemente chiari, dall'altra ho qualche dubbio nella fase di scrittura del codice. Evidentemente la premessa che tutto mi è sufficientemente chiaro probabilmente è fala.

Provo a fare una sorta di premessa: in definitiva un array multidimensionale è un puntatore ad n array. Ad esempio il seguente array bidimensioneale:

	int matrice[2][3];
Può essere pensato come int (*matrice)[3]. In definitiva si potrebbe dire che un array multidimensionale è sempre un array monodimensionale.

Adesso, per addentrarmi nei miei dubbi, assegno all'array matrice dei valori:

	static int matrice[2][3] = {{1,2,3},{4,5,6}};
Dal momento che il nome di un array ne definisce il puntatore dovrei poter scrivere la seguente funzione per stampare l'array bidimensionale sopra dichiarato.

void stampaUno(int v[], int dimCol)
{
    for(int c = 0; c < dimCol; c++)
    {
        printf("%d ", v[c]);
    }
    printf("\n");
}
Come vederemo nella main ogni volta che verrà invocata la funzione stampaUno il puntatore v sarà incrementato alla i-esima riga dell'array bidimensionale.
La funzione stampaUno funziona correttamente e non viene segnalato niente di anomalo come previsto.

Se è vero che il nome di un vettore è un puntatore allora è possibile definire la funzione stampaDue:

void stampaDue(int* v, int dimCol)
{
    for(int c=0;c<dimCol;c++)
    {
        printf("%d ", v[c]);
    }
    printf("\n");
}
Tuttavia, pur andando a buon fine la compilazione e funzionando correttamente, in fase di compilazione ottengo il seguente warning "warning: passing argument 1 of 'stampaDue' from incompatible pointer type" quando effettuo la chiamata:

    for(int i=0;i<2;i++){
        stampaDue(matrice+i, 3);
    }
    
Mi sfugge il motivo eppure dovrebbe essere un corretto puntatore rispetto alla definizione della funzione. In effetti, in fase di dichiarazione del prototipo l'IDE mi dà il seguente messaggio:
"int *' but argument is of type 'int (*)[3]", probabilmente mi vuol indicare che in quel modo ho un puntatore ad array la cui lunghezza sarebbe varibaile, ma ne mio caso essa è costante a tre? In definitiva è sbagliata tale funzione, seppur funzionante?

A questo punto dichiaro una funzione del tutto simile a stampaUno ma con un'invocazione leggermente diversa.

void stampaTre(int v[], int dimCol)
{
    for(int c=0;c<dimCol;c++)
    {
        printf("%d ", v[c]);
    }
    
    printf("\n");
}


La sua invocazione a questo punto viene effettuata nel seguente modo:

    for(int i=0;i<2;i++)
    {
        stampaTre((vettBid+i), 3); /** Passo il puntatore incrementano le righe **/
    }
Pur funzionando anche questa implementazione, in fase di compilazione, ottengo il seguente messaggio:
"note: expected 'int *' but argument is of type 'int (*)[3]" alla riga della definizione del prototipo della funzione.

void stampaTre(int v[], int dimCol);
Anche in questo caso devo intendere la notifica come l'ho interpreta poco sopra?
Faccio presente però che il prototipo è identico alla funzione stampaUno, il quale prototipo non scatena alcun messaggio.

Noto però che se commento la riga dell'invocazione della funzione
stampaTre((vettBid+i), 3);
Il messaggio scompare.

Infine, ho scritto una quarta dichiarazione di funzione "stampaQuattro", la quale dovrebbe essere quella "migliore" che riporto di seguito, ma all'interno della quale non capisco come si acceda e si utlizzi:

void stampaQuattro(int (*matrice)[3], int dimCol)
{
    for(int c=0;c<dimCol;dimCol++)
    {
        printf("%d ", *matrice[c]);
    }
    
 printf("\n");
}
Detto questo, vi sarò grato delle considerazioni che vorrete fornirmi circa i miei dubbi e su quanto ho implementato. E se si può concludere che un array MULTI-dimensionale può essere ricondotto a un array monodimensione che punta ad N puntatori di dimensione D. In altre parole un putatore che punta N puntatori di dimensione D. Pertanto, nel caso di un array bidimensionale sarà possibile inoltrare l'interno array bidimensionale a[R][C] una funzione passando a[C].

Mi pare di capire che per poter lavorare in questo modo le funzioni devono poter conoscere a priori le dimensioni degli array. Infine, non esiste un modo per capire se iterano il puntatore a si è arrivati all'ultima riga, corretto? Rafforzando l'idea che le dimensioni devono essere ben note a priori.

Di segutio, per semplicità, riporto il piccolo codice di prova che ho effettuato.

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

static int matrice[2][3] = {{1,2,3},{4,5,6}};

void stampaUno(int v[], int dimCol);
void stampaDue(int* v, int dimCol);
void stampaTre(int v[], int dimCol);
void stampaQuattro(int (*v)[3], int dimCol);



int main(int argc, char** argv) {
    for(int i=0;i<2;i++){
        stampaUno(matrice[i], 3);
    }
    printf("stampa DUE\n");
    for(int i=0;i<2;i++){
        stampaDue(matrice+i, 3);
    }
    printf("stampa TRE\n");
    for(int i=0;i<2;i++)
    {
        stampaTre((matrice+i), 3);
    }
    

    printf("stampa QUATTRO\n");
    for(int i=0;i<2;i++)
    {
        stampaQuattro((matrice+i), 3);
    }

    return (EXIT_SUCCESS);
}

void stampaUno(int v[], int dimCol)
{
    for(int c = 0; c < dimCol; c++)
    {
        printf("%d ", v[c]);
    }
    printf("\n");
}

void stampaDue(int* v, int dimCol)
{
    for(int c=0;c<dimCol;c++)
    {
        printf("%d ", v[c]);
    }
    printf("\n");
}

void stampaTre(int v[], int dimCol)
{
    for(int c=0;c<dimCol;c++)
    {
        printf("%d ", v[c]);
    }
    
    printf("\n");
}


void stampaQuattro(int (*matrice)[3], int dimCol)
{
    for(int c=0;c<dimCol;c++)
    {
        printf("%d ", (*matrice)[c]);
    }
    
    printf("\n");
}
Ancora grazie infinite a tutti, per il vostro prezioso contributo che mi consente spesso una migliore comprensione delle cose.

8 Risposte

  • Re: Array bidimensionali (multidimensionali)

    Il problema di stampaDue() non è nella funzione, ma nella chiamata. La funzione si aspetta come primo argomento un puntatore ad int, invece tu gli passi un puntatore ad un array di 3 interi. Per risolvere il problema basta sostituire matrice+i con matrice o equivalentemente *(matrice+i).

    La funzione stampaTre() non ha senso di esistere, in quanto è identica a stampaUno() (se vuoi fare esperimenti sulla chiamata, utilizza direttamente quest'ultima). Il motivo per cui il compilatore ti segnala un errore è lo stesso di prima, la funzione si aspetta un int*, ma tu gli passi un int(*)[3].

    Per quanto riguarda stampaQuattro(), int(*matrice)[3] è un puntatore ad un array di 3 interi, quindi la chiamata matrice+i stavolta è corretta.

    Alcune considerazioni... array e puntatori sono due cose diverse; un array è un insieme di elementi dello stesso tipo che occupano locazioni di memoria consecutive, mentre un puntatore è una variabile in grado di contenere l'indirizzo di memoria di un'altra variabile.
    L'identificatore di un array nella maggior parte dei casi viene declassato a puntatore al primo elemento (ciò è quello che accade per esempio quando passiamo un array come argomento ad una funzione, un'eccezione invece è quando utilizziamo l'identificatore dell'array come argomento dell'operatore sizeof), dove con "declassamento" si intende una conversione con perdita di informazioni riguardanti la dimensione (il numero di elementi dell'array) e il tipo (int[5] e int[6] sono entrambi convertiti in int*).
    Per quanto detto si deduce che quando scriviamo gli argomenti di una funzione le scritture int *v e int v[] sono assolutamente equivalenti; il C/C++ offre la possibilità di riportare l'argomento usando la notazione con le parentesi quadre, ma a conti fatti le [] più esterne sono sinonimo di * (ossia scrivere come argomento di una funzione int (*m)[3] è come scrivere int m[][3]).
    Quanto detto in precedenza spiega anche perchè un array statico bi-dimensionale (per esempio int m[2][3]) non può essere passato ad una funzione avente come argomento una variabile di tipo int**, infatti nel momento in cui m viene declassato, esso diventa un puntatore al primo elemento, ossia un puntatore ad un array di 3 interi, ma il problema è che int** e int(*)[3] sono due tipi diversi.

    Detto questo, vi sarò grato delle considerazioni che vorrete fornirmi circa i miei dubbi e su quanto ho implementato. E se si può concludere che un array MULTI-dimensionale può essere ricondotto a un array monodimensione che punta ad N puntatori di dimensione D. In altre parole un putatore che punta N puntatori di dimensione D.

    Non sono sicuro di aver capito ciò che intendi dire, in ogni caso un array multidimensionale di dimensione D può essere interpretato come un array di N array di dimensione D-1.

    Spero di aver risposto alle tue domande, se hai ancora qualche dubbio o ti accorgi che ho scritto qualche sciocchezza fammi sapere!
  • Re: Array bidimensionali (multidimensionali)

    Ciao Nippolo,
    ti ringrazio davvero moltissimo, per l'estesa ed esauriente risposta. Alcune cose, sono onesto devo ancora digerirle del tutto.

    La prima parte della tua risposta credo di averla assimilata in toto, onestamente, ma per colpa mia, mi sono perso un po' quando dici:
    Quanto detto in precedenza spiega anche perchè un array statico bi-dimensionale (per esempio int m[2][3]) non può essere passato ad una funzione avente come argomento una variabile di tipo int**, infatti nel momento in cui m viene declassato, esso diventa un puntatore al primo elemento, ossia un puntatore ad un array di 3 interi, ma il problema è che int** e int(*)[3] sono due tipi diversi.
    Se puoi, quando puoi, potresti spiegarmi meglio? Grazie.

    Infine, provo a spiegarmi quando dico in maniera un po' sommaria:
    Detto questo, vi sarò grato delle considerazioni che vorrete fornirmi circa i miei dubbi e su quanto ho implementato. E se si può concludere che un array MULTI-dimensionale può essere ricondotto a un array mono dimensione che punta ad N puntatori di dimensione D. In altre parole un puntatore che punta N puntatori di dimensione D. Pertanto, nel caso di un array bidimensionale sarà possibile inoltrare l'interno array bidimensionale a[R][C] una funzione passando a[C].
    Nella mia precedente affermazione, vole alludere a come in definitiva gli array multidimensionali siano un'astrazione necessaria, credo, al punto da poter dire che da un punto di vista di un calcolatore non esistono. La natura della memoria di un calcolatore è certamente "monodimensionale". Pertanto un array bidimensionale o multidimensionale che si voglia deve in qualche modo poter essere rappresentato da un array monodimensionale. A tal propostio, in termini di efficienza riflettevo, ammesso che siano corrette le mie valutazioni, quale sia il modo migliore di accedere ai dati.

    Provo a spiegarmi, partendo proprio dal più semplice degli array multidimensioneli, cioè il bidimensionale. A tal caso riprendo la matrice bidimensionale che avevo esposto nel precedente post:
    
    static int matrice[2][3] = {{1,2,3},{4,5,6}};
    
    Supponendo che il formalismo concesso dal linguaggio di programmazione (non certo esclusivo del C) sia una semplificazione, un artificio, per poter accedere a un'entità monodimensionale qual è la memoria, deve poter esistere la possibilità di utilizzare un puntatore che consenta di accedere "linearmente" ai dati (o anche a salti). In effetti, sperimentando, qualcosa del genere è possibile fare, ma vorrei generalizzare il concetto rispetto alle dimensioni degli "spazi vettore". Si pensi ad esempio a un classico cubo e comprendere quale sia la modalità più efficiente, pensando a grandi moli di dati, ma anche da un punto meramente concettuale, al fine di comprendere meglio il funzionamento sottostante, . Non so se poi è una "pippa" mia, in quanto, poi, è il compilatore che risolve quanto vorrei già in fase di programmazione effettuare.

    Mi spiego meglio con un esempio: immagino che questo array bidimensionale possa essere risolto all'interno di uno spazio monodimensionale qual è la memoria di un pc o di un microcontrollore.

    La normale traduzione in una vettore bidimensionale in uno spazio monodimensionale sarà, data la seguente notazione [posizione, valore], dalle seguenti coppie:
    [0,1][1,2][2,3][3,4][4,5][5,6]

    Pertanto se alla mia funzione passo il puntatore alla matrice (int *) posso scorrere il mio spazio monodimensionale come se fosse bidimensionale.
    Questo perché int * è si un puntatore a un intero, ma avanzando scorro le locazioni di inizio delle mie righe (dunque l'inizio degli array riga).

    Se questo è vero può essere scritta una funzione:
    
    void arrayBidiMensionaleSimulatoConMonoDimensionale(int *a, int righe, int colonne)
    {
        for(int r=0;r<righe;r++){
            for(int c=0;c<colonne;c++){
                printf("%d ", a[(r*colonne)+c]);                                               
            }
            printf("\n");
        }
    }
    
    E in effetti le ipotesi sono confermate dalla pratica.
    Il caso può essere "generalizzato" anche per un matrice a tre dimensioni.

    Ma adesso vengo al dunque, di quello che evidentemente non ho ancora compreso. Se (int *matrice)[3] è un puntatore a un array di dimensione 3 dovrei poter scorrere almeno inizialmente tutti valori colonna della prima riga. Con un sistema simile alla funzione precedente. Come se fosse uno spazio monodimensionale. Dove sbaglio? Sbaglio da un punto di vista teorico o implementativo?

    Nello specifico dichiaro il seguente prototipo:
    
    void arrayBidiMensionaleSimulatoConMonoDimensionalePuntatoreAdArray(int (*)[3], int righe, int colonne);
    
    Mentre l'implementazione è:
    
    void arrayBidiMensionaleSimulatoConMonoDimensionalePuntatoreAdArray(int (*a)[3], int righe, int colonne)
    {
        //printf("%d %d\n", a[0], a[3]);
            
            //for(int r=0;r<righe;r++){
                //a+=r;
                for(int c=0;c<colonne;c++){
                     printf("%d ",*a[c]);
                }
            printf("\n");
        //}
    }
    
    Ma dà valori direi del tutto "arbritari". È evidente che continuo a sbagliare e/o a non comprendere. Sono le funzioni di quest'ultimo caso mal definite?

    Grazie davvero per la pazienza e per le clamorose lacune che certamente mostrerò di avere.
    Grazie ancora!
  • Re: Array bidimensionali (multidimensionali)

    Ciao!

    deckard ha scritto:


    La prima parte della tua risposta credo di averla assimilata in toto, onestamente, ma per colpa mia, mi sono perso un po' quando dici:

    Nippolo ha scritto:


    Quanto detto in precedenza spiega anche perchè un array statico bi-dimensionale (per esempio int m[2][3]) non può essere passato ad una funzione avente come argomento una variabile di tipo int**, infatti nel momento in cui m viene declassato, esso diventa un puntatore al primo elemento, ossia un puntatore ad un array di 3 interi, ma il problema è che int** e int(*)[3] sono due tipi diversi.

    Se puoi, quando puoi, potresti spiegarmi meglio? Grazie.
    In effetti qui spiego qualcosa che non hai chiesto, quindi è comprensibile il fatto che tu sia rimasto un attimo spaesato, nel senso che ti domandi per quale motivo ho introdotto questa questione. Il motivo è che quanto detto in precedenza mi permetteva di fornire una spiegazione ad un dubbio (relativo al passaggio a funzione di un array) che assale molti neofiti (anche me all'inizio), ossia "se ad un argomento di tipo int* possiamo passargli un array statico monodimensionale, perché ad un argomento di tipo int** non possiamo passargli un array statico bidimensionale?". Tutto qui!

    deckard ha scritto:


    Nella mia precedente affermazione, vole alludere a come in definitiva gli array multidimensionali siano un'astrazione necessaria, credo, al punto da poter dire che da un punto di vista di un calcolatore non esistono. La natura della memoria di un calcolatore è certamente "monodimensionale". Pertanto un array bidimensionale o multidimensionale che si voglia deve in qualche modo poter essere rappresentato da un array monodimensionale.
    In effetti sì, nel senso che un array Ddimensionale (con D>1) non è altro che un vettore (ossia un array monodimensionale) di puntatori ad array D-1dimensionali.

    deckard ha scritto:


    ...
    Ma dà valori direi del tutto "arbritari". È evidente che continuo a sbagliare e/o a non comprendere. Sono le funzioni di quest'ultimo caso mal definite?
    Ragioniamo sul seguente codice compilabile:
    #include <iostream>
    
    using namespace std;
    
    void fun(int (*a)[3], int colonne)
    {
        for(int c = 0; c < colonne; ++c)
        {
            printf("%d ", *a[c]);
        }
    }
    
    int main()
    {
        int m[2][3] = {{1,2,3},{4,5,6}};
        fun(m, 3);
    }
    Il motivo per cui questo codice ti restituisce un output "strano" (e non 1,2,3), è dovuto semplicemente al fatto che l'operatore di indicizzazione array (cioè []) ha una precedenza maggiore rispetto all'operatore di dereferenziazione (cioè *). Infatti per risolvere il problema basta scrivere (*a)[c] (che tra l'altro coincide con a[0][c]).

    Dalle parti commentate della funzione arrayBidiMensionaleSimulatoConMonoDimensionalePuntatoreAdArray() presumo stavi facendo qualche "esperimento" o sbaglio?

    Non so se ho risposto a tutte le tue domande, in ogni caso se hai qualche dubbio cerca di tradurlo in codice, in questo modo diventa più semplice capirsi!
  • Re: Array bidimensionali (multidimensionali)

    Nippolo ha scritto:


    Ciao!

    deckard ha scritto:


    La prima parte della tua risposta credo di averla assimilata in toto, onestamente, ma per colpa mia, mi sono perso un po' quando dici:

    Nippolo ha scritto:


    Quanto detto in precedenza spiega anche perchè un array statico bi-dimensionale (per esempio int m[2][3]) non può essere passato ad una funzione avente come argomento una variabile di tipo int**, infatti nel momento in cui m viene declassato, esso diventa un puntatore al primo elemento, ossia un puntatore ad un array di 3 interi, ma il problema è che int** e int(*)[3] sono due tipi diversi.

    Se puoi, quando puoi, potresti spiegarmi meglio? Grazie.
    In effetti qui spiego qualcosa che non hai chiesto, quindi è comprensibile il fatto che tu sia rimasto un attimo spaesato, nel senso che ti domandi per quale motivo ho introdotto questa questione. Il motivo è che quanto detto in precedenza mi permetteva di fornire una spiegazione ad un dubbio (relativo al passaggio a funzione di un array) che assale molti neofiti (anche me all'inizio), ossia "se ad un argomento di tipo int* possiamo passargli un array statico monodimensionale, perché ad un argomento di tipo int** non possiamo passargli un array statico bidimensionale?". Tutto qui!

    deckard ha scritto:


    Nella mia precedente affermazione, vole alludere a come in definitiva gli array multidimensionali siano un'astrazione necessaria, credo, al punto da poter dire che da un punto di vista di un calcolatore non esistono. La natura della memoria di un calcolatore è certamente "monodimensionale". Pertanto un array bidimensionale o multidimensionale che si voglia deve in qualche modo poter essere rappresentato da un array monodimensionale.
    In effetti sì, nel senso che un array Ddimensionale (con D>1) non è altro che un vettore (ossia un array monodimensionale) di puntatori ad array D-1dimensionali.

    deckard ha scritto:


    ...
    Ma dà valori direi del tutto "arbritari". È evidente che continuo a sbagliare e/o a non comprendere. Sono le funzioni di quest'ultimo caso mal definite?
    Ragioniamo sul seguente codice compilabile:
    #include <iostream>
    
    using namespace std;
    
    void fun(int (*a)[3], int colonne)
    {
        for(int c = 0; c < colonne; ++c)
        {
            printf("%d ", *a[c]);
        }
    }
    
    int main()
    {
        int m[2][3] = {{1,2,3},{4,5,6}};
        fun(m, 3);
    }
    Il motivo per cui questo codice ti restituisce un output "strano" (e non 1,2,3), è dovuto semplicemente al fatto che l'operatore di indicizzazione array (cioè []) ha una precedenza maggiore rispetto all'operatore di dereferenziazione (cioè *). Infatti per risolvere il problema basta scrivere (*a)[c] (che tra l'altro coincide con a[0][c]).

    Dalle parti commentate della funzione arrayBidiMensionaleSimulatoConMonoDimensionalePuntatoreAdArray() presumo stavi facendo qualche "esperimento" o sbaglio?

    Non so se ho risposto a tutte le tue domande, in ogni caso se hai qualche dubbio cerca di tradurlo in codice, in questo modo diventa più semplice capirsi!
    Gentilissimo Nippolo,
    ti sono davvero grato per gli ulteriori approfondimenti e la tua gentilezza. Devo fare ancora esercizio affinché alcuni formalisimi e concetti possano diventare agevoli e spontanei! Ora comprendo la tua precedente dissertazione.

    A proposito del codice commentato, hai ben intuito che volevo:volevo sperimentare, penso che tu abbia capito perfettamente anche cosa!!!

    Adesso vado avanti, con le tue osservazioni e correzioni e ti faccio sapere dove riesco ad arrivare. Il mio obiettivo, almeno per fini di comprensione, è poter usare solo aritmentica dei puntatori.

    Grazie, e sopratutto omaggio la tua disponibilità a aiutare alla comprensione attraverso la tua conoscenza.

    Garzie di cuore.
  • Re: Array bidimensionali (multidimensionali)

    Di niente!
  • Re: Array bidimensionali (multidimensionali)

    Nippolo ha scritto:


    Di niente!
    Gentilissimo Nippolo,

    ecco il termine delle mie sperimentazioni che avevi già intuito. Scrivo, non perché abbia scoperto chissà di sensazionale, ma per ricambiare, simbolicamente, il tempo che mi hai offerto.

    Alla fine, forse ci sarei già arrivato qualche passaggio fa, sono riuscito, credo, a prendere dimestichezza con la navigazione di un array MULTI-DIMENSIONALE per mezzo della sola aritmetica dei puntatori.
    Anche se ho già in qualche modo implementato un approccio per ad un array di D>2, il prossimo passo per me è arrivare a scrivere un enunciato che consenta la generalizzazione.


    Di seguito le implementazioni intermedie per la navigazione della nostra ormai "celebre" matrice[2][3]:
    void implUno(int (*a)[3],int colonne)
    {
            for(int c=0;c<colonne;c++){
                printf("%d ", (*a)[c]); /** corretto tutte le colonne di tutte le righe facendo avanzare a *=r; */
            }
        
    }
    
    void implDue(int (*a)[3],int righe, int colonne)
    {
                for(int r=0;r<righe;r++){
                a+=r;
                for(int c=0;c<colonne;c++){
                  printf("%d ",(*a)[c]);  
                }
            printf("\n"); 
        }
    }
    
    
    void implTre(int (*a)[3], int righe, int colonne)
    {
        int *p = *a; 
        /**
         * IN DEFINITIVA E' POSSIBILE SCORERE IN MODO MONODIMENSIONALE UNA ARRAY
         * BIDIMENSIONALE O E N-DIMENSIONALE SOLTANTO UANDO IL PUNTATORE ARRAY RIGA.
         * INCREMENTANDO IL PUNTATORE RIGA P NEL SEGUENTE MODO
         * p+(r*colonne)+c)
         * Quindi sarà possibile accere alla riga 0 colonna 2 semplicemente scrivendo
         * p+(0*NUMERO_COLONNE+2)
         * IN GENERALE SARA' p+(riga_corrente + NUMERO_COLONNE_TOTALI + collona_corrente)
         * ADESSO DEVO FARE ESPERIMENTI CON 3 - 4 DIMENSIONI.
         */
    
            for(int r=0;r<righe;r++){
                for(int c=0;c<colonne;c++){
                    printf("%d", *(p+(r*colonne)+c));
                }
        }
    }
    
    È possibile dare una definizione generale per un array multidimensionale di D>2, proverò.Inolte, mi sto interrogando, se questo modo fare ricerce di specifici elementi sia più o meno effieciente della notazione per indici [j], ovviamente ipotizzando moli piuttosto grandi di dati.

    Grazie, cercherò, di assimilare e far proprie le considerazioni che mi hai fatto in questo bellissimo, per me, thread, e migliorare il mio livello di disivontulara con i puntatori.
    Ogni tua consdierazione è più che gradita.

    Grazie ancora.
  • Re: Array bidimensionali (multidimensionali)

    Alcune considerazioni:

    implDue() è sbagliata, infatti se il numero di righe sono più di due, la funzione ritorna un output evidentemente errato. Te ne puoi accorgere lanciando il seguente codice:
    #include <stdio.h>
    
    void implDue(int (*a)[3], unsigned int righe, unsigned int colonne)
    {
        for(unsigned int r = 0; r < righe; ++r)
        {
            a += r;
            for(unsigned int c = 0; c < colonne; ++c)
            {
                printf("%d ", (*a)[c]);
            }
            printf("\n");
        }
    }
    
    int main()
    {
        int matrice[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
        implDue(matrice, 3, 3);
    }
    Il problema è nella riga a+=r, infatti ipotizzando che a sia uguale a 0, avremmo la seguente successione: 0 1 3 6 10 15 21 28 ...

    Per quanto riguarda implTre() puoi evitare di dichiarare la variabile p scrivendo direttamente *(*a+r*colonne+c). Inoltre tale implementazione presuppone che gli elementi della matrice siano contigui in memoria; ciò è sempre vero (così ho letto) nel caso di array statici, ma non nel caso di array multidimensionali allocati dinamicamente.
    Un'implementazione che andrebbe bene in entrambi i casi è la seguente:
    void implQuattro(int (*a)[3], unsigned int righe, unsigned int colonne)
    {
        for(unsigned int r = 0; r < righe; ++r)
        {
            for(unsigned int c = 0; c < colonne; ++c)
            {
                printf("%d ", *(*(a + r) + c));
            }
            printf("\n");
        }
    }
  • Re: Array bidimensionali (multidimensionali)

    Caro Nippolo,
    ti ringrazio per questo magnifico thread, almeno per me che sono al principio del mio percorso. Ti ringrazio per avermi dissipato dubbi e dato risposta ai miei errori, grazie per l'ultima tua elegante implementazione, che tra l'altro risolve un difetto della mia precedente. Adesso a me cercare di rielaborare tutto quanto detto, fare pratica e rendere questi concetti più naturali con la pratica e l'esperienza.

    Ora riprendo il mio studio verso altri argomenti, certamente leggerai ancora qualche mio dubbio, o di altre mie lacune.
    Sinceramente grazie.
Devi accedere o registrarti per scrivere nel forum
8 risposte