[C] Passaggio di array 2-dimensionali alle function

Messaggioda sab.a » 11/11/2019, 19:15

Salve, ho dei dubbi riguardo il passaggio di un array 2-dimensionale a una function.
Per l'esame devo scrivere una function che effettui l'operazione C=C+A*B dove A, B e C sono matrici quadrate di dimensione N. La function deve avere la seguente testata:

void matmat(int LDA, int LDB, int LDC, float *A, float *B, float *C, int N)

Il mio dubbio nasce dal fatto che fino ad ora per passare una matrice ad una function ho sempre scritto "float A[][LDA]" nel caso della matrice A e non "*A"
Credo che le due istruzioni siano equivalenti, dal momento che in entrambi i casi viene passato l'indirizzo della prima variabile dell'array in memoria, ma vorrei una conferma. In caso contrario varierebbe qualcosa nell'implementazione della mia function? Mi spiego meglio. Al momento ho scritto:

void matmat(int LDA, int LDB, int LDC, float *A, float *B, float *C, int N){
int i, j, k;
for (i=0, i<N, i++) {
for (j=0, j<N, j++) {
for (k=0, k<N, k++) {
C[i][j]=C[i][j]+A[i][k]*B[k][j];
}}}
}

E' corretto scrivere così oppure è necessario l'uso delle "&"?
Inoltre a cosa serve passare anche le leading dimensions LDA, LDB, LDC se poi non vengono esplicitamente utilizzate nel passaggio delle tre matrici alla function?
Spero di aver spiegato bene i miei dubbi. Grazie in anticipo
sab.a
Starting Member
Starting Member
 
Messaggio: 11 di 11
Iscritto il: 26/02/2018, 19:10

Re: [C] Passaggio di array 2-dimensionali alle function

Messaggioda Leyxargon » 11/11/2019, 21:57

Partiamo innanzitutto dal parlare di puntatori, si tratta di particolari variabili che al loro interno non contengono valori ma indirizzi di memoria. Un esempio pratico è
Codice:
int x = 5;
int *pun = &x;

printf("Indirizzo di x: %x\n", &x);
printf("Contenuto di x: %d\n", x);
printf("Indirizzo della variabile puntata da pun: %x\n", pun);
printf("Contenuto della variabile puntata da pun: %d\n", *pun);

Eseguendo questo programma si ottiene un risultato simile a questo
Codice:
ESECUZIONE PROGRAMMA:
Indirizzo di x: c02f1f54
Contenuto di x: 5
Indirizzo della variabile puntata da pun: c02f1f54
Contenuto della variabile puntata da pun: 5

Nel linguaggio C si definiscono i due operatori * e &, rispettivamente di dereferenziazione e di indirizzo di.
Analizzando il codice sopra scritto, abbiamo:
  • nella prima stampa la visualizzazione dell'indirizzo di x (tramite l'operatore "indirizzo di")
  • nella seconda stampa la visualizzazione del contenuto di x
  • nella terza stampa visualizziamo il contenuto di pun, cioè l'indirizzo alla quale punta pun che in tal caso è l'indirizzo di x
  • nella quarta stampa visualizziamo il contenuto della variabile puntata da pun (tramite l'operatore di dereferenziazione), cioè il contenuto di x

Ora un array non è altro che un intervallo di puntatori, difatti è possibile accedervi mediante l'algebra dei puntatori, in altre parole la deferenziazione di ogni i-esimo elemento dell'array, cioè *(A+i) dove A è un array di dimensione n, ed i è un indice che va da 0 ad n-1. Analogamente è possibile accedere agli elementi di un array con la notazione ad array A[i], che si occupa in automatico di dereferenziare l'i-esimo elemento.

Al contrario di come effettivamente utilizziamo le matrici, il calcolatore vede in memoria una zona "lineare", ed è per questo motivo che risulta necessario passare la dimensione n di una matrice (es. int M[][n]), in modo tale da distinguere le grandezze di un array 2D.
Come per gli array monodimensionali, anche per le matrici è possibile utilizzare la notazione a puntatore, dove per accedere all'elemento contenuto nella i-esima colonna (di dimensione n) e j-esima riga si usa *(M + i*n + j).

Adesso passiamo all'algoritmo della tua consegna. Mi sorge spontaneo un dubbio, si parla solo di matrici quadrate? Perché in tal caso la dimensione da ricordare è solo una (N), quindi è superfluo il passaggio dei parametri int LDA, int LDB e int LDC, se invece l'algoritmo deve trattare anche matrici rettangolari, allora sono necessari tutti i parametri scritti nell'intestazione.

Il mio dubbio nasce dal fatto che fino ad ora per passare una matrice ad una function ho sempre scritto "float A[][LDA]" nel caso della matrice A e non "*A"

Corretto. *A è un parametro che corrisponde o ad un puntatore o al più un array monodimensionale, infatti la tua implementazione mi sembra corretta eccetto proprio nell'intestazione, poiché stai trattando un puntatore come un puntatore a puntatore (scusami il gioco di parole).

In conclusione ribadisco il mio dubbio sulla intestazione. Se si tratta di matrici allora i parametri da passare sono necessariamente float A[][LDA], float B[][LDB] e float C[][LDC], altrimenti mi verrebbe da pensare ad una traccia leggermente differente.
Ultima modifica di Leyxargon il 12/11/2019, 17:43, modificato 2 volte in totale.
Leyxargon
Starting Member
Starting Member
 
Messaggio: 7 di 8
Iscritto il: 06/11/2019, 12:44

Re: [C] Passaggio di array 2-dimensionali alle function

Messaggioda Super Squirrel » 12/11/2019, 00:55

Il mio dubbio nasce dal fatto che fino ad ora per passare una matrice ad una function ho sempre scritto "float A[][LDA]" nel caso della matrice A e non "*A"
Credo che le due istruzioni siano equivalenti, dal momento che in entrambi i casi viene passato l'indirizzo della prima variabile dell'array in memoria, ma vorrei una conferma.

Dal punto di vista del "tipo" le due istruzioni non sono equivalenti, un argomento del tipo int A[][N] (equivalente a int (*A)[N]) si aspetta un puntatore ad un array di N interi e non un semplice puntatore ad int.

P.S.
Occhio all'algoritmo adoperato nel codice.
Super Squirrel
Junior Member
Junior Member
 
Messaggio: 381 di 383
Iscritto il: 16/05/2013, 22:05

Re: [C] Passaggio di array 2-dimensionali alle function

Messaggioda apatriarca » 12/11/2019, 01:27

Da molti punti di vista il supporto ad array multidimensionali in C è molto carente. Devi inserire quasi tutte le dimensioni e queste dimensioni devono essere costanti. Al fine di supportare matrici di dimensioni qualsiasi è comune passarle come array monodimensionali e poi usare qualcosa come
Codice:
A[i * cols + j]

per accedere ai singoli elementi. Questo è il tipo di codice e accesso agli elementi che il tuo professore si aspetta nel tuo esercizio.
apatriarca
Moderatore
Moderatore
 
Messaggio: 5316 di 5329
Iscritto il: 08/12/2008, 20:37
Località: Londra

Messaggioda vict85 » 12/11/2019, 12:28

Leyxargon ha scritto:Restando in tema di puntatori, una matrice (array bidimensionale) corrisponde ad un puntatore di puntatore, o ad un array di puntatori, dove ogni elemento dell'array corrisponde al puntatore di una riga della matrice.


Non è assolutamente vero. L'utilizzo di array di puntatori per le matrici è comune nei corsi universitari ma non l'ho mai visto usare da nessun'altra parte. Gli array di puntatori sono ovviamente usati, ma per altri usi.

Un matrice del tipo int matrice[3][4] non è altro che un array di dimensione 12 a cui si accede usando un puntatore ad array di dimensione 4. In altre parole il codice
Codice:
int f( int matrice[3][4] );

può essere sostituito dai codici
Codice:
int f( int matrice[][4] );
oppure
Codice:
int f( int (*matrice)[4] );
con gli stessi significati. Mentre
Codice:
int f( int** matrice );
non è per nulla equivalente.

Insomma, la memoria è continua. Array e puntatori non sono esattamente la stessa cosa e non vanno confusi.
vict85
Moderatore
Moderatore
 
Messaggio: 9971 di 10020
Iscritto il: 16/01/2008, 00:13
Località: Berlin

Re:

Messaggioda Leyxargon » 12/11/2019, 17:23

vict85 ha scritto:
Leyxargon ha scritto:Restando in tema di puntatori, una matrice (array bidimensionale) corrisponde ad un puntatore di puntatore, o ad un array di puntatori, dove ogni elemento dell'array corrisponde al puntatore di una riga della matrice.


Non è assolutamente vero. L'utilizzo di array di puntatori per le matrici è comune nei corsi universitari ma non l'ho mai visto usare da nessun'altra parte. Gli array di puntatori sono ovviamente usati, ma per altri usi.

Un matrice del tipo int matrice[3][4] non è altro che un array di dimensione 12 a cui si accede usando un puntatore ad array di dimensione 4. In altre parole il codice
Codice:
int f( int matrice[3][4] );

può essere sostituito dai codici
Codice:
int f( int matrice[][4] );
oppure
Codice:
int f( int (*matrice)[4] );
con gli stessi significati. Mentre
Codice:
int f( int** matrice );
non è per nulla equivalente.

Insomma, la memoria è continua. Array e puntatori non sono esattamente la stessa cosa e non vanno confusi.


Ti ringrazio per la segnalazione, mi ero espresso male. Infatti successivamente parlavo dell'accesso tramite la notazione a puntatore

Come per gli array monodimensionali, anche per le matrici è possibile utilizzare la notazione a puntatore, dove per accedere all'elemento contenuto nella i-esima colonna (di dimensione n) e j-esima riga si usa *(M + i*n + j).


Questo proprio perché in memoria viene visto in maniera continua.
Leyxargon
Starting Member
Starting Member
 
Messaggio: 8 di 8
Iscritto il: 06/11/2019, 12:44


Torna a Informatica

Chi c’è in linea

Visitano il forum: Nessuno e 6 ospiti