Newsgroup: it.comp.lang.c
Titolo: controllo sulla calloc

Salve sto scrivendo un programma per la mia tesi (credo mi conosciate dato
che inondando il NG di messaggi, anzi, scusatemi.
Vorrei sapere come faccio a controllare se sono andata a buon fine queste 2
calloc:
  plus0   = (long*)calloc(n+1, sizeof(long));
  (*w)    = (long*)calloc((*m)+1, sizeof(long));
Cosě va bene? E' corretto?
if((plus0 = (long*)calloc(n+1, sizeof(long)))==NULL) {
    perror("Errore di allocazione");
    return 1;
}
if(( (*w)    = (long*)calloc((*m)+1, sizeof(long)))==NULL) {
    perror("Errore di allocazione");
    return 1;
}

 Cosě va bene? E' corretto?
Piu' o meno va bene pero'
1) includi <stdlib.h> e elimina il cast quindi scrivi
plus0 = calloc(n+1,sizeof(long));  e
*w = calloc etc.etc.
poi IMHO e' piu' leggibile spezzare allocazione
e controllo su due righe. quindi dopo l'allocazione controlli:
plus0 = calloc(n+1,sizeof(long));
if (plus0==NULL)  ERRORE;
oppure equivalentemente
if (! plus0)  ERRORE;
ciao,
g.

 wrote:

 long *plus0;
 long **w;
 if ( (plus0 = calloc(n+1, sizeof *plus0))==NULL ) {
     perror("Errore di allocazione");
     return EXIT_FAILURE;
 }
 
 if ( (*w = calloc(*m+1, sizeof **w))==NULL ) {
     perror("Errore di allocazione");
     return EXIT_FAILURE;
 }
 
-- 
Horst


Sicuro che va bene ed il cast non è necessario? Me lo hanno insegnato così
!!!

Me lo hanno insegnato così !!!
Te lo hanno insegnato male.  Persino sul K&R seconda versione c'è la
raccomandazione di "castare" il valore di ritorno di malloc() ma
prontamente è stato stampato l'Errata Corrige.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it


Ok.
P.S.: Grazie davvero a tutti per la mano che mi state dando

 oppure equivalentemente
Poichč alloco una 20ina di array č davvero un gran casino di codice. Avevo
pensato di passare plus0 ad una funzione che faceva il controllo.
Purtroppo non sono tutti array di long. Mica sapreste dirmi come faccio a
dichiarare nel prototipo un tipo generico in modo da poter passare plus0
(che č di long), oppure weight (che č di int) o altri array di altri tipi?
Dovrei scrivere qualcosa tipo:
checkAlloc(void *array){
    if(array==NULL)
        errore
}
Cosě funziona? Grazie

 Cosě funziona? Grazie
puoi fare semplicemente qualcosa tipo:
void * MyCalloc(int quanti, int sz, char *e)
{
   char *p;
   p=calloc(quanti,sz);
   if (p) return p;
   perror(e);
   return NULL;
}
da usare come
int *arr;
arr = MyCalloc(1000,sizeof(int),"arr");
a questo punto puoi sbizzarrirti con una
bella e perigliosa #define fatta cosi'
(il nome magari scelto meglio...)
#define MyCal(var,qq,tipo) var=MyCalloc(qq,sizeof(tipo),#var)
e a questo punto invece di scrivere
arr = MyCalloc(1000,sizeof(int),"arr");
puoi scrivere direttamente
MyCal(arr,1000,int);
o sei hai double **x;
MyCal(*xxx,133,double*);
in modo analogo puoi definire una funzione che alloca
matrici bidimensionali (prima un vettore di puntatori alle
righe e poi le righe),
ciao,
g.

 chi chede aiuto.
Shhh... silenzio.


"Giovanni Resta" <g.resta...@iit.cnr.itTAGLIAMI> ha scritto nel
messaggio news:%9Ite.23931$b5.11...@news3.tin.it...

GRazie ma preferirei una funzione che si limiti a controllare se
l'allocazione č riuscita.
Quindi va bene se faccio questo?
void checkMem(void *arr){
    if (arr==NULL){
        perror("Errore");
        exit(1);
    }
}
E poi in chiamata:
checkMem(a);
checkMem(b);
Considerando che:
long *a;
int *b;
Con calloc fatta !!!
Grazie

 }
Direi di si.
ciao,
.g

 ha scritto nel messaggio
news:d99ac2$muc$2...@newsfeed.cineca.it...


 Funziona vero? E' corretto?
Assolutamente no!
Tra le altre cose non dovrebbe neanche lasciartelo
compilare!
non puoi lavorare in quel modo su void *
perche' quando il compilatore va a compilare
la tua funzione non puo' sapere di fatto quanto
e' grosso il dato che deve copiare
Chiaramente c'e' una bella differenza a seconda
che tu gli passi un vettore di char, di int o magari
di double, visto che tipicamente occupano quantita'
di memoria diverse.
Puoi usare direttamente la funzione memcpy,
definita in  string.h
void *memcpy(void *dest, const void *src, size_t n);
che copia un certo numero di bytes.
quindi farai una cosa tipo
memcopy(x1,y1,n*sizeof(int));
ciao,
g.

 void *memcpy(void *dest, const void *src, size_t n);
Cioč posso usare questa per copiare l'intero array?
GRande !!!
L'array destinazione va allocato prima, ovviamente.
Allora, come mai nel caso visto prima (controllo della calloc) potevo usare
void *?
GRazie

Ciobin wrote:

perche' quando usi una funzione come ad esempio calloc per allocare
o memcpy per copiare, dici esplicitamente quanti bytes allocare o muovere.
infatti per usare la memcpy devi spostare n*sizeof(il tipo) bytes
e glielo devi dire esplicitamente.
invece nel tuo programma con il void * dereferenziato come
x[i]=y[i]
il compilatore nel mentre che tu gli passi un puntatore a void, cioe'
praticamente un puntatore "puro" ad un indirizzo di memoria,
non ha idea di quanto lungo (1,2,4,8,.. bytes) sia lungo il tipo
di dato puntato, quindi non saprebbe quanti byte copiare nel
tradurre l'istruzione x[i]=y[i].
Una cosa simile a quella che vorresti tu si fa agevolmente in C++ (del
quale sono molto ignorante) con dei meccanismi di tipo template
che permettono di scrivere codice in qualche modo parametrico rispetto
al tipo del dato.
Nel caso del C potresti (a parte che usare memcpy e' piu' semplice)
definirti tu una copyarrI per interi una copyArrL per long,
una per double etc.etc.
poi pero' dovresti invocare quella giusta.
ciao,
g.

 ha scritto nel messaggio
news:d99do5$oak$1...@newsfeed.cineca.it...

Ma non dovrebbe usare per le strinche? Va bene anche con array di int e
long?

"Giovanni Resta" <g.resta...@iit.cnr.itTAGLIAMI> ha scritto nel
messaggio news:1VXte.26201$b5.12...@news3.tin.it...
[CUT]
Grazie davvero per la mille spiegazioni. Praticamente 3 anni di universitą
sono stati inutili.
Spero continuerai a darmi una mano, mi manca poco alla fine della tesi.
GRAZIE DI VERO CUORE !!!!

 long? 
copia zone di memoria. quello che c'e' dentro non gli interessa,
purche' le due zone di memoria che gli indichi non si sovrappongano,
nel qual caso (o in caso di dubbio) si usa la funzione memmove.
per copiare stringhe (che sono array di caratteri in cui un carattere
nullo finale funge da delimitatore) c'e' la funzione
strcpy che e' diversa perche' operando su stringhe non
ha bisogno che gli venga specificata la lunghezza degli operandi.
ciao,
g.

 MyCal(arr,1000,int);
Ciao a tutti,
stavo leggendo il thread e non sono davvero riuscito a capire questo 
passaggio:
Alla funzione MyCalloc si passa l'indirizzo della stringa che conterra' 
il possibile errore, ma non capisco perche' dalla #define gli si passa 
#var... qualcuno sarebbe cosi' gentile da fare un po' di luce?
Ciao :-)
-- 
Er Baitch
http://baitch.altervista.org/


La MyCalloc era pensata per questo scopo:
gli passo
1) il numero di oggetti da allocare
2) il size del tipo da allocare
3) una stringa da stampare in caso di errore.
quello che volevo ottenere con la macro era di fare coincidere
il nome dell'array da allocare con il messaggio di errore
(in modo che dal messaggio di errore fosse chiaro quale array "sforava").
Per non dover usare esplicitamente due volte il nome,
in questo modo
int *Pippo;
Pippo = MyCalloc(666,sizeof(int),"Pippo");
ho definito una macro che utilizza un meccanismo
detto "stringification":
http://docs.freebsd.org/info/cpp/cpp.info.Stringification.html
In pratica se nel testo di una macro premetto un "#" ad un
nome di un argomento, l'argomento verra' trasformato in
una stringa.
Quindi in
#define MyCal(var,qq,tipo) var=MyCalloc(qq,sizeof(tipo),#var)
se passo var = Pippo allora nella espansione della macro
var verra' sostituito da Pippo e #var da "Pippo".
Quindi invocare
MyCal(Pippo,666,int); corrisponde ad eseguire
Pippo = MyCalloc(666,sizeof(int),"Pippo");
Tutto questo per far vedere come una cosa puo' essere fatta.
Poi in un programma "serio e corposo" magari l'uso delle
macro andra' evitato o limitato allo stretto indispensabile,
perche' per la maggior parte degli usi sono sostituibili
da codice normale (usando const e inline) che ha il vantaggio
di essere piu' facilmente debuggabile.
ciao
g.

 3) una stringa da stampare in caso di errore.
wow... conciso e preciso :-)
grazie :-)
-- 
Er Baitch
http://baitch.altervista.org/
-- Fortune of the day --
Under a government which imprisons any unjustly, the true place for a
just man is also a prison.
		-- Henry David Thoreau