PDA

View Full Version : [C] Puntatori tripli e array di matrici


AnonimoVeneziano
14-10-2005, 19:48
Ciao boys.

Oggi per divertimento ho iniziato a scrivere un po' di roba riguardante le matrici.

Per motivi logistici che non sto a spiegarvi mi risulterebbe molto utile riuscire a passare a una funzione del tipo

float **funz(float ***);


un array di matrici del tipo


float Matrici[2][5][5]


Il problema è che il passaggio semplice (come si fa con i puntatori ed array unidimensionali) :


funz(Matrici)


Non funziona.

Ora mi trovo veramente in difficoltà , perchè ho sempre pensato agli array come "costanti di tipo puntatore" , e perciò con la stessa aritmetica e modus operandi dei normali puntatori.

Infatti il tutto funziona perfettamente con gli array unidimensionali, ma già quando si passa a quelli bidimensionali (matrici) scattano i problemi.

Vi faccio un esempio di un programmino che ho scritto apposta per esplicare il problema :


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

int a[5], *p;

int main(int argc, char **argv)

{
p = a;

printf("0x%X\n", p);
printf("0x%X\n", a);
printf("0x%X\n", *p);
printf("0x%X\n", *a);

return 0;

}


Come vedete nel programma viene fatta una cosa semplicissima. Viene dichiarato un array "a" e poi un puntatore "p" entrambi di tipo int.
Successivamente viene assegnato al puntatore "p" il valore di "a", ossia l'indirizzo del primo elemento di "a". Successivamente con le "printf()" scrivo a schermo una serie di valori in esadecimale. In particolare scrivo l'indirizzo contenuto in "p", quello contenuto in "a" e i valori puntati rispettivamente. L'output del programma è:


melchior@melchior:~$ ./prova3
0x8049660
0x8049660
0x0
0x0


L'output è proprio quello che mi aspettavo. Gli indirizzi contenuti in "a" e in "p" sono identici e il valore puntato da quell' indirizzo è anch'esso identico (in questo caso = a "0" perchè l'array è stato inizializzato automaticamente dal compilatore a "0").

Ora ho provato a trasformare l'array in una matrice e il puntatore in un doppio puntatore in questo modo :


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

int a[5][5], **p;

int main(int argc, char **argv)

{
p = a;

printf("0x%X\n", p);
printf("0x%X\n", a);
printf("0x%X\n", *p);
printf("0x%X\n", *a);

return 0;

}


A questo punto mi aspettavo un output simile al precedente, solo che al posto del valore "0" nelle ultime 2 printf mi sarei ritrovato l'indirizzo del primo elemento del primo array della matrice "a" che ovviamente è uguale per entrambe le chiamate di printf , ma invece :


melchior@melchior:~$ ./prova3
0x80496A0
0x80496A0
0x0
0x80496A0


Come vedete l'indirizzo contenuto in"a" e in "p" è sempre lo stesso, solo che se faccio il dereferimento di "p" ottengo inspiegabilmente "0", mentre facendo quello di "a" ottengo l'indirizzo contenuto in "a" stesso (che dovrebbe anche essere l'indirizzo del primo array di "a").

Chiaramente se faccio un doppio dereferimento di "p" con "**p" ottengo un "Segmentation Fault".

GCC mi da anche un warning alla compilazione del secondo programmino che nel caso del primo non appare :


melchior@melchior:~$ gcc provaschif.c -o prova3
provaschif.c: In function 'main':
provaschif.c:9: warning: assignment from incompatible pointer type


Sinceramente però non riesco a capire cosa sbaglio :(

Grazie a tutti quelli che mi aiuteranno

Ciao

PS= Scusate per la lunghezza.

Qu@ker
14-10-2005, 20:20
#include <stdio.h>

int a[5][5], (*p)[5];

int main()
{
p = a;

printf("%p\n", p);
printf("%p\n", a);
printf("%p\n", *p);
printf("%p\n", *a);

return 0;
}

AnonimoVeneziano
14-10-2005, 20:28
#include <stdio.h>

int a[5][5], (*p)[5];

int main()
{
p = a;

printf("%p\n", p);
printf("%p\n", a);
printf("%p\n", *p);
printf("%p\n", *a);

return 0;
}


Interessante, il problema è che non mi posso permettere una cosa del genere, dato che all' inizio non conosco neanche una delle dimensioni dell' array (e quindi non potrei scrivere quel [5]) .

Come potrei fare in questo caso senza sapere neanche una delle dimensioni dell'array?

Grazie

Ciao

AnonimoVeneziano
14-10-2005, 20:33
Interessante, il problema è che non mi posso permettere una cosa del genere, dato che all' inizio non conosco neanche una delle dimensioni dell' array (e quindi non potrei scrivere quel [5]) .

Come potrei fare in questo caso senza sapere neanche una delle dimensioni dell'array?

Grazie

Ciao


Ho provato a fare :

#include <stdio.h>

int a[5][5], (*p)[];

int main()
{
p = a;

printf("%p\n", p);
printf("%p\n", a);
printf("%p\n", *p);
printf("%p\n", *a);

return 0;
}


Sintassi a me sempre stata sconosciuta e funziona, il problema è che trasformando la cosa per un puntatore triplo non funziona, ne :

(*p)[ ][ ] :

melchior@melchior:~$ gcc provaschif.c -o prova3
provaschif.c:4: error: array type has incomplete element type

e nemmeno

(**p)[ ] (viene lo stesso problema che ho all' inizio)

Come fare?

Grazie

Ciao

sirus
14-10-2005, 21:21
:asd: io quando ho fatto un programmino che lavorava sulle matrici bidimensionali con allocazione dinamica et simila sono arrivato ai Puntatori a Puntatori ;) e il passaggio di parametri era banalmente una cosa simile


typedef riga float*;
typedef matrice riga*;

matrice funzione(matrice) {
...
}

non dovrebbe essere diverso...comunque ora sono sul PC2 e non ho a disposizione il programma domani ti posto il procedimento corretto ;) e provi a vedere se riesci a fare funzionare il programma ;)

Qu@ker
14-10-2005, 21:39
Non sono sicuro di capire: se non hai le dimensioni come pensi di gestirlo, il puntatore?
Comunque, la sintassi (*p)[] dovrebbe essere un'estensione del GCC, anche se qualcosa di simile e' prevista anche nel C99. In ogni caso, l'array flessibile deve essere l'ultimo elemento, per cui con tre indici diventerebbe, ad es., (*p)[5][].
Tutto sommato, perche' non passi l'indirizzo come void *?

AnonimoVeneziano
15-10-2005, 01:17
:asd: io quando ho fatto un programmino che lavorava sulle matrici bidimensionali con allocazione dinamica et simila sono arrivato ai Puntatori a Puntatori ;) e il passaggio di parametri era banalmente una cosa simile


typedef riga float*;
typedef matrice riga*;

matrice funzione(matrice) {
...
}

non dovrebbe essere diverso...comunque ora sono sul PC2 e non ho a disposizione il programma domani ti posto il procedimento corretto ;) e provi a vedere se riesci a fare funzionare il programma ;)


Niente da fare , non funziona. Inoltre nel typedef "riga" e "float*" e "matrice" e "riga*" dovrebbero essere invertiti

Ciao

AnonimoVeneziano
15-10-2005, 01:22
Non sono sicuro di capire: se non hai le dimensioni come pensi di gestirlo, il puntatore?
Comunque, la sintassi (*p)[] dovrebbe essere un'estensione del GCC, anche se qualcosa di simile e' prevista anche nel C99. In ogni caso, l'array flessibile deve essere l'ultimo elemento, per cui con tre indici diventerebbe, ad es., (*p)[5][].
Tutto sommato, perche' non passi l'indirizzo come void *?


Metti che ho una roba del genere :

int arrayMatr[2][5][5];

funz(arrayMatr);

La mia funzione non può sapere a priori che che nella seconda parentesi ci sarà il valore 5, perchè , volendo , io potrei scrivere qualsiasi valore, quindi non posso dichiarare "funz()" come :

funz(int (*aMatr)[5][ ])

, ma dovrei dichiararla in modo generico come :

funz(int ***aMatr)

Questo però non me lo fa fare in modo corretto :stordita:

sirus
15-10-2005, 09:00
ecco come ho fatto io:

/* definizione di un tipo di dato di nome Matrice di tipo **float */
typedef float *Riga;
typedef Riga *Matrice;

...

Matrice initMatrice(Matrice FMatrice, unsigned int FRows, unsigned int FColumns) {
FMatrice = new float*[FRows]; // allocazione di un array di *float
for(unsigned int j = 0; j < FRows; j++) {
FMatrice[j] = new float[FColumns]; // allocazione di un array di float
}
/* per ogni array di puntatori a float viene definito un array di float
al suo interno, questo array permetterà di immagazzinare i dati */
return FMatrice;
}

...

ho messo la funzione più semplice che ho scritto (mi faceva allocare la matrice dinamicamente) comunque il passaggio di parametri (funzionante) l'ho fatto come sopra :)

non credo che aggiungendo un * in più...ossia creando un puntatore a puntatore a puntatore le cose cambino :(

spero di essere stato più chiaro e spero di aver capito il problema che avevi :stordita: altrimenti :muro:

DomusP45
19-01-2014, 09:40
Invece io ho un problema leggermente diverso, ma simile.

Ho una serie di matrici 4x4 double. Sono tutti array "double [4][4]".

Sono 9 array di questo tipo. Io vorrei legarli ad un indice o altro array, da passare poi ad una funzione, così con l'indice, accedere a quella matrice.

Tipo, int elencomatrici[9] = non so come assegnargli le 9 matrici

funzione_prova (int elenco){

...

elenco[1] <--deve restituirmi la 2° matrice

}


come si fa questa cosa?

bancodeipugni
19-01-2014, 13:41
uhm...quasi 9 anni fa

vediamo se qualcuno ancora riceve le notifiche:fagiano:

Daniels118
22-01-2014, 09:50
#include <stdio.h>

#define N 2
#define W 5
#define H 5

typedef struct TMatrici {
float matrici[N][W][H];
} TMatrici;

float media(TMatrici m) {
int i, j, k;
float avg = 0;
for (i = 0; i < N; i++) {
for (j = 0; j < W; j++) {
for (k = 0; k < H; k++) {
avg += m.matrici[i][j][k];
}
}
}
return avg / (N * W * H);
}

int main(int argc, char *argv[]) {
int i, j, k;
float avg;
float l = 0;
TMatrici m;
for (i = 0; i < N; i++) {
for (j = 0; j < W; j++) {
for (k = 0; k < H; k++) {
m.matrici[i][j][k] = l;
l++;
}
}
}
avg = media(m);
printf("%f\n", avg);
system("PAUSE");
return 0;
}