ricavare la dimensione di un array in c usando un puntatore

Area di discussione libera.

Moderatore: Staff

Regole del forum
1) Rispettare le idee altrui.
2) Evitare le offese dirette.
3) Leggere attentamente le risposte ricevute
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Rispondi
Avatar utente
absinthe
Iper Master
Iper Master
Messaggi: 2354
Iscritto il: dom 15 mag 2005, 0:00
Nome Cognome: Matteo Nunziati
Slackware: 12.1 - defunct
Kernel: 2.6.32-5-amd64
Desktop: gnome
Distribuzione: debian squeeze
Località: Prato
Contatta:

ricavare la dimensione di un array in c usando un puntatore

Messaggio da absinthe »

chiedo scusa per il titolo un pò nebuloso ma non mi bastavano i caratteri per descivere la cosa...
purtroppo sono abbastatnza arrugginito in c, vi spiego il problema: ho un array di strutture da me realizzate, per semplicità diciamo:

Codice: Seleziona tutto

//my struct
typedef struct _apoint {
int x;
int y;
} point;
questo array è statico, viene definito nel main da me, senza allocazione dinamica etc...:
devo passare l'array ad una funzione che lo manipola . tale funzione è generica e fa parte di una libreria scritta da me ma a cui linko staticamente diversi eseguibili che devo gestire. non mi ricordo come (se) fare per far capire la dimansione del vettore alla funzione. pensavo di fare un prototipo di funzione tipo:

Codice: Seleziona tutto

//prototype
void funzione_libreria(point *ptr);

e di passare l'array tramite la chiamata:

Codice: Seleziona tutto

int main () {
point data[10];
funzione_libreria(data);
//...
return 0;
}
il fatto è che non so come ricavarmi la dimensione dell'array,se implemento nella funzione qualcosa tipo:

Codice: Seleziona tutto

void funzione_libreria(point *ptr) {
//...
int dimension=(int) sizeof(ptr)/sizeof(ptr[0]);
//...
}
succede un ovvio macello... non mi ricordo come venirne a capo :-/
qualche anima pia mi ricorda come fare? o dove leggere come fare? denghiù!

M

Avatar utente
corrado
Linux 2.x
Linux 2.x
Messaggi: 218
Iscritto il: dom 13 feb 2005, 0:00
Nome Cognome: corrado
Slackware: current
Kernel: 2.6.29.6-smp
Desktop: kde-4
Località: isola del liri
Contatta:

Re: ricavare la dimensione di un array in c usando un puntat

Messaggio da corrado »

absinthe ha scritto:chiedo scusa per il titolo un pò nebuloso ma non mi bastavano i caratteri per descivere la cosa...
purtroppo sono abbastatnza arrugginito in c, vi spiego il problema: ho un array di strutture da me realizzate, per semplicità diciamo:

Codice: Seleziona tutto

//my struct
typedef struct _apoint {
int x;
int y;
} point;
questo array è statico, viene definito nel main da me, senza allocazione dinamica etc...:
devo passare l'array ad una funzione che lo manipola . tale funzione è generica e fa parte di una libreria scritta da me ma a cui linko staticamente diversi eseguibili che devo gestire. non mi ricordo come (se) fare per far capire la dimansione del vettore alla funzione. pensavo di fare un prototipo di funzione tipo:

Codice: Seleziona tutto

//prototype
void funzione_libreria(point *ptr);

e di passare l'array tramite la chiamata:

Codice: Seleziona tutto

int main () {
point data[10];
funzione_libreria(data);
//...
return 0;
}
il fatto è che non so come ricavarmi la dimensione dell'array,se implemento nella funzione qualcosa tipo:

Codice: Seleziona tutto

void funzione_libreria(point *ptr) {
//...
int dimension=(int) sizeof(ptr)/sizeof(ptr[0]);
//...
}
succede un ovvio macello... non mi ricordo come venirne a capo :-/
qualche anima pia mi ricorda come fare? o dove leggere come fare? denghiù!

M
Forse dico una cosa stupida (non ho ben capito il problema), ma se definissi la dimensione dell'array come una direttiva o una costante? Tipo :

Codice: Seleziona tutto

#define ARRAYDIM  10
oppure

Codice: Seleziona tutto

const int arraydim = 10;
Se sbaglio non infierire...

Saluti
corrado

Avatar utente
tgmx
Linux 4.x
Linux 4.x
Messaggi: 1336
Iscritto il: ven 28 apr 2006, 14:40
Slackware: 14.1
Desktop: KDE 4
Località: Ancona

Messaggio da tgmx »

aggiungi un parametro alla funzione e passagli la dimensione dell'array...

Avatar utente
ildiama
Linux 3.x
Linux 3.x
Messaggi: 536
Iscritto il: mar 27 dic 2005, 16:49
Slackware: mine
Kernel: 2.6.alto..
Desktop: KDE4
Località: Senigallia
Contatta:

Messaggio da ildiama »

Sì, la cosa che dici è strana. O forse ho capito male io. Comunque... in C non si dichiarano array senza dimensione. Cioè, per dichiararlo devi fare una cosa tipo

Codice: Seleziona tutto

point p[dimensione];
dove dimensione è un intero ed è il numero di elementi. Da lì la dimensione dell'array si può ottenere con una cosa tipo

Codice: Seleziona tutto

sizeof(point) * dimensione
Se basta così ok. Se non ho capito una mazza chiedi pure. Ciao

Avatar utente
elettronicha
Master
Master
Messaggi: 1712
Iscritto il: mer 13 apr 2005, 0:00
Località: Torino
Contatta:

Messaggio da elettronicha »

voto per la soluzione proposta da corrado.
l'array è statico e va allocato, quindi basta impostare una variabile globale con una direttiva o con il modificatore "const" (meglio la prima).
rileggi la documentazione dell'operatore sizeof, esso restituisce la dimensione in byte. comunque non ho capito cosa significhi:

int dimension=(int) sizeof(ptr)/sizeof(ptr[0]);

Avatar utente
tgmx
Linux 4.x
Linux 4.x
Messaggi: 1336
Iscritto il: ven 28 apr 2006, 14:40
Slackware: 14.1
Desktop: KDE 4
Località: Ancona

Messaggio da tgmx »

La soluzione di corrado non credo vada bene perchè se la funzione appartiene ad una libreria e una libreria si presume debba essere portabile non si può basare su una variabile globale.

E' di gran lunga preferibile, secondo me, che la funzione accetti oltre al puntatore all'array anche un intero contenente le sua dimensione.

Avatar utente
elettronicha
Master
Master
Messaggi: 1712
Iscritto il: mer 13 apr 2005, 0:00
Località: Torino
Contatta:

Messaggio da elettronicha »

è vero! non ci avevo fatto caso che fosse una libreria.

Avatar utente
phobos3576
Staff
Staff
Messaggi: 2980
Iscritto il: dom 17 apr 2005, 0:00
Slackware: 13.1
Kernel: 2.6.37-smp
Desktop: KDE 4.5.3

Re: ricavare la dimensione di un array in c usando un puntat

Messaggio da phobos3576 »

absinthe ha scritto:... il fatto è che non so come ricavarmi la dimensione dell'array,se implemento nella funzione qualcosa tipo:

Codice: Seleziona tutto

void funzione_libreria(point *ptr) {
//...
int dimension=(int) sizeof(ptr)/sizeof(ptr[0]);
//...
}
succede un ovvio macello...
Succede un ovvio macello perché, all'interno di funzione_libreria, l'identificatore ptr rappresenta l'indirizzo di una struttura point e non una struttura point; di conseguenza, sizeof(ptr) ti restituisce la dimensione di un indirizzo di memoria!

Il metodo che tu intendevi usare consiste nello scrivere:

Codice: Seleziona tutto

int dimensione_array = sizeof(nome_array) / sizeof(nome_array[0]);
Il problema è che in C, per motivi di efficienza, quando si passa un array ad una funzione in realtà viene passato l'indirizzo del primo elemento dell'array stesso!
Allora, come ha scritto tgmx, aggiungi un parametro alla funzione e usalo per passare la dimensione dell'array. In alternativa, puoi creare l'array come vettore di puntatori a elementi di tipo point; l'ultimo elemento del vettore lo fai puntare a NULL in modo che la funzione sappia quando ha raggiunto la fine del vettore stesso.

Avatar utente
lamarozzo
Linux 3.x
Linux 3.x
Messaggi: 732
Iscritto il: gio 14 lug 2005, 0:00
Desktop: xfce
Distribuzione: archlinux
Località: Roma

Messaggio da lamarozzo »

tgmx ha scritto:aggiungi un parametro alla funzione e passagli la dimensione dell'array...
IMHO questo e' il modo corretto di farlo in C. Negli array del C non c'e' nessuna informazione sulla lunghezza dello stesso e quindi la lunghezza va passsata direttamente alla funzione che deve manipolarlo. Altrimenti c'e' il rischio di andare a leggere/scrivere su altri indirizzi di memoria con effetti imprevedibili!

Se sei in C++ invece puoi usare il template vector della STL.

Avatar utente
absinthe
Iper Master
Iper Master
Messaggi: 2354
Iscritto il: dom 15 mag 2005, 0:00
Nome Cognome: Matteo Nunziati
Slackware: 12.1 - defunct
Kernel: 2.6.32-5-amd64
Desktop: gnome
Distribuzione: debian squeeze
Località: Prato
Contatta:

Re: ricavare la dimensione di un array in c usando un puntat

Messaggio da absinthe »

phobos3576 ha scritto:
absinthe ha scritto:... il fatto è che non so come ricavarmi la dimensione dell'array,se implemento nella funzione qualcosa tipo:

Codice: Seleziona tutto

void funzione_libreria(point *ptr) {
//...
int dimension=(int) sizeof(ptr)/sizeof(ptr[0]);
//...
}
succede un ovvio macello...
Succede un ovvio macello perché, all'interno di funzione_libreria, l'identificatore ptr rappresenta l'indirizzo di una struttura point e non una struttura point; di conseguenza, sizeof(ptr) ti restituisce la dimensione di un indirizzo di memoria!
già l'"ovvio" era riferito a questo: all'inizio avevo implementato così senza riflettere, poi mi ero accorto della vaccata ma anche del fatto che non mi veniva in mente nessuna soluzione se non quella di passare la dimensione... credevo ci fosse un modo per far calcolare la "lunghezza" in automatico...
Il metodo che tu intendevi usare consiste nello scrivere:

Codice: Seleziona tutto

int dimensione_array = sizeof(nome_array) / sizeof(nome_array[0]);
Il problema è che in C, per motivi di efficienza, quando si passa un array ad una funzione in realtà viene passato l'indirizzo del primo elemento dell'array stesso!
Allora, come ha scritto tgmx, aggiungi un parametro alla funzione e usalo per passare la dimensione dell'array. In alternativa, puoi creare l'array come vettore di puntatori a elementi di tipo point; l'ultimo elemento del vettore lo fai puntare a NULL in modo che la funzione sappia quando ha raggiunto la fine del vettore stesso.
mmm... grazie! credo che userò la prima soluzione: mi pare la più rapida anche nell'ottica di dover passare la libreria a qualcun'altro!

M

Avatar utente
absinthe
Iper Master
Iper Master
Messaggi: 2354
Iscritto il: dom 15 mag 2005, 0:00
Nome Cognome: Matteo Nunziati
Slackware: 12.1 - defunct
Kernel: 2.6.32-5-amd64
Desktop: gnome
Distribuzione: debian squeeze
Località: Prato
Contatta:

Messaggio da absinthe »

elettronicha ha scritto:voto per la soluzione proposta da corrado.
l'array è statico e va allocato, quindi basta impostare una variabile globale con una direttiva o con il modificatore "const" (meglio la prima).
rileggi la documentazione dell'operatore sizeof, esso restituisce la dimensione in byte. comunque non ho capito cosa significhi:

int dimension=(int) sizeof(ptr)/sizeof(ptr[0]);
beh... nel mio caso niente ;) in generale, se implementato con criterio, serve per ricavarsi la dimensione di un array, come ha scritto anche phobos3576. ad esempio io lo utilizzo negli applicativi quando mi serve di avere a portata di mano la dimensione di una stringa definita dal preprocessore. esempio stupido in un file pippo.h:

Codice: Seleziona tutto

#ifndef PIPPO_H
#define PIPPO_H

#define CODENAME "edgy"
#define CODENAMESIZE sizeof(CODENAME)/sizeof(CODENAME[0])

#endif //pippo.h
in questo modo modifichi il nome in codice nel file .h e ovunque nel resto dei sorgenti tutto si aggiorna automaticamente: stringa del nome in codice e lunghezza associata

M.

Rispondi