Newsgroup: it.comp.lang.c
Titolo: Re: Secondo voi è corretto?

 TNX
Si`, tutto a posto, ma, secondo me, sarebbe piu` conveniente definire
checkMem come macro:
#define checkMem(ptr) if(array==NULL){\
                        perror("Errore di allocazione");\
                        exit(1);\
                        }



"Zero" <frank_sanna@SPAMMER_AL_CONFINO_IN_SIBERIAlibero.it> ha scritto nel
messaggio news:hIhue.16557$D7.4...@twister1.libero.it...

Cioč? E poi come la uso? Perchč converrebbe? Grazie

                         }
Le macro, in questi casi, vanno sempre evitate, a favore delle funzioni.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 checkMem(xopt = calloc(n+1, sizeof(int)));
Non che abbia molto senso.  A mio parere non č mai bene che una funzione
(a meno che non esplicitamente progettata per quello) si preoccupi di
gestire un caso di errore come questo.  Nel tuo caso un if č piů che
sufficiente.
if ((xopt=calloc(...))) ...
else
  printf("errore...");


 funzioni.
Perché?
Saluti

 Cioè? E poi come la uso? Perchè converrebbe? Grazie
Una macro con un "prototipo" del genere si usa come una funzione
(tenendo ben presente, per evitare guai, che, effettivamente, non lo
è). Quindi, prendendo come esempio il codice da te fornito:
char *p=malloc(20+1);
memCheck(p);
Però, memCheck(), essendo una macro, viene sostituita dal preprocessore
del compilatore con quel blocco if; la situazione successiva alla sua
sostituzione diverrebbe la seguente:
char *p=malloc(20+1);
if(array==NULL){
  perror("Errore di allocazione");
  exit(1);
};
Come ben saprai, l'ultimo ';', nel caso in oggetto, è un'istruzione
vuota: è inutile. Tutto funziona anche senza quel ';', ma non sarebbe
il caso di "richiamare" la macro senza il consueto punto e virgola.
Credo sia questo il motivo per il quale Andrea Laforgia ha deprecato
l'uso delle macro in simili evenienze. Vero?
Spero di non aver detto falsità e di non esser stato fuorviante.
Saluti.

 è). 
Quindi, nei fatti, non si usa come funzione.  Ti sfido a scrivere una
macro sbagliata e a scovare dov'è l'errore a compilazione, visto che
nessun compilatore produce un errore indicandoti la riga "espansa" dal
preprocessore, ma riferendosi semplicemente al sorgente di partenza.  Il C
è già un linguaggio complicato di per sè, se ci si mette anche da soli a
complicarsi la vita...


 Perché?
Perché esistono metodi alternativi (e più sicuri) per fare le stesse cose.
Nel nuovo standard, ad esempio, sono previste le inline functions (mutuate
dal C++) che sono sicure ed efficienti.  Tieni anche presente che una
macro non ha controllo sui parametri passati e che è bene sempre
racchiuderli tra parentesi tonde (per evitare errori dovuti all'espansione
da parte del preprocessore nel caso uno o più parametri contengano
virgole).  Insomma, le macro sono un'inutile complicazione, meglio non
usarle.


 virgole). 
.."virgole" o comunque vi siano operatori che facciano "collidere" certe
operazioni.
Esempio:
#include <stdio.h>
#define calc1(a,b,c) (a*b*c)
#define calc2(a,b,c) ((a)*(b)*(c))
int main()
{
    printf("%d\n", calc1(1,1+2,3)); /* scrive 7 */
    printf("%d\n", calc2(1,1+2,3)); /* scrive 9 */
    return 0;


  printf("errore...");
Non condivido. Controllare il valore di ritorno di malloc
in ogni chiamata e gestendo la cosa secondo me e' l'approccio
errato. A parte che moltiplica il numero di righe di codice
la probabilita' che il codice di gestione di un esaurimento
memoria sia corretto e' praticamente *nulla* (come scrivi i
test ?); per fortuna e' anche bassa anche la probabilita' che
quel codice venga eseguito davvero (l'utente nel 90% dei casi
si e' stufato di vedere la lucetta dell'hard disk impazzita
e il PC piantato e ti ha gia' salutato con ctrl-alt-del ben
prima che malloc fallisca).
Io preferisco avere una mia malloc custom che *garantisce*
che al ritorno la memoria sia stata allocata; la malloc
normale la chiamo solo per le allocazioni di grandi aree
dati in cui il voler proseguire dopo un fallimento
dell'allocazione non e' qualcosa di irragionevole.
Avere una propria funzione di allocazione torna utile anche
per molte altre cose (ad esempio posso usare un allocatore
di debug, limitare la quantita' di memoria totale allocabile
per evitare di portare il sistema in trash mode o attivare
dei warning di memoria in esaurimento).
Andrea


Per ovviare al problema del ";" la macro puo` essere scritta:
#define checkMem(ptr) do{if(ptr==NULL){\
                           perror("Errore di allocazione");\
                           exit(1);\
                         } while(0)
Dopo while(0) e` necessario mettere il ";" per cui checkMem(ptr); 
diventa corretto.



[CUT]
Ok, ma il fatto è che dovrei scrivere una funzione per ogni tipo di
allocazione.
Nel mio caso dovrei scriverne una per vettore di interi ed una per vettore
di long. Io ne vorrei solo una !!!

 Questo succede solo a chi scrive le macro in modo sbagliato.
Irrilevante.
Le macro offrono la possibilità di sbagliare, quindi le macro vanno
evitate.


 che al ritorno la memoria sia stata allocata; 
Infatti, se rileggi il mio msg, escludo le funzioni che siano
esplicitamente progettate per gestire memoria.


 
Anche scrivere codice offre la possibilita` di sbagliare, quindi il 
codice non va scritto :-(


 codice non va scritto :-(
Infatti č cosě.
Finora non c'č nulla di meglio (anche se si stanno facendo studi a
proposito) che "scrivere" del codice.  Quindi, visto che scrivere codice č
pressoché obbligatorio, bisogna capire che cosa usare o non usare.  Le
macro vengono facilmente sostituite dalle inline functions: stessa
efficienza, maggiore sicurezza.
