PDA

Visualizza la versione completa : [Preprocessore C] Wrapper macro


/* Coder */
08-05-2004, 04:30
inline int Fileno(FILE* fpStream)
{
int in;

if((in = fileno(fpStream)) < 0)
err_sys("(Module: %s) - ERROR fileno() failed", gargv[0]);

return in;
}


Devo trasformare in macro la funzione sovrastante.
E' un wrapper di fileno() per controllare il codice di errore comodamente.
Il mio problema è che "inline" è una richiesta, non un comando, e spesso vedo che i compilatori la ignorano per i motivi più disparati.
Per tagliare la testa al toro volevo ridefinire tutti i miei wrapper come macro.
Non riesco però a scrivere l'equivalente codice per il preprocessore.

Ho provato così:




#define Fileno(fp) \
{ \
int iRet; \
((iRet = fileno(fp)) < 0) ? rett : err_sys("(Module: %s) - ERROR fileno() failed", gargv[0]); \
}

La macro la utilizzerei poi tipo così:

int main()
{
FILE* fpProva;
int ifd = Fileno(fpProva);

// ......

return 0;
}



Non funziona e dà un errore compilando con g++ 3.2.
Mi sta venendo il dubbio che non si possa proprio fare.

Qualche idea?

:sonno:

/* Coder */
08-05-2004, 06:13
#define Fileno(fpStream) (1? \
({ \
int iRet; \
if((iRet = fileno(fpStream)) < 0) \
err_quit("(Module: %s) - ERROR fileno() failed\n", gargv[0]); \
iRet; \
}):0)


E' un'ora che ci sto sopra e finalmente ho risolto.
Io non so cosa ci sia sotto la parola chiave "inline", sta di fatto che la funzione macrata guadagna 5 secondi per ogni migliardo di chiamate.
La funzione inline va a fare qualche cosa che fa sprecare circa 5 ns a ogni chiamata. Vi metto l'output del tempo di CPU qui sotto.



Istructions load: 1000000000
Macros vs Inline
Getting times...

Inline: 20.620000
Macro: 15.620000


Ho seri dubbi sul funzionamento di inline.
Boh, può essere che mi sbaglio.

CIAO !

/* Coder */
08-05-2004, 06:29
#define MBEGIN (1?({
#define MEND }):0)
#define RETURN

#define ciccio(iParam) \
MBEGIN \
int a, b; \
a = 1; \
b = 2; \
if((a < iParam) \
puts("Ciao pippo !"); \
RETURN b;
MEND


Ma lol, ho provato e sta roba funziona.
Sembra che uno riesca a farsi i propri comodi nelle macro come fossero funzioni.
Wow un nuovo linguaggio di programmazzione, CMACRO++
Ma dov'è la fregatura?
Sembra troppo bello.

CIAO !

/* Coder */
08-05-2004, 09:27
Mancava la \ nello script di sopra.
E' così:



#define BEGIN (1?({
#define END }):0)
#define RETURN

#define ciccio(iParam) \
BEGIN \
int a, b; \
a = 1; \
b = 2; \
if((a < iParam) \
puts("Ciao pippo !"); \
RETURN b; \
END


Ho preso altri tempi intanto, guardate qua:



Istructions load: 100000000
Macros vs Inline
Getting times...

Inline: 2.150000 s
Macro: 0.220000 s


:eek: :eek: :eek:

:master:

:bhò:

/* Coder */
09-05-2004, 04:05
Allora ho scoperto l'acqua calda.

CIAO !
:cry: :biifu:

internet
09-05-2004, 18:59
Originariamente inviato da /* Coder */
Mancava la \ nello script di sopra.
E' così:



#define BEGIN (1?({
#define END }):0)
#define RETURN

#define ciccio(iParam) \
BEGIN \
int a, b; \
a = 1; \
b = 2; \
if((a < iParam) \
puts("Ciao pippo !"); \
RETURN b; \
END


Ho preso altri tempi intanto, guardate qua:



:eek: :eek: :eek:

:master:

:bhò:

hai compilato con -O3 ?
se no, prova a compilarlo con questo flag e rifai i bench

per le macro guarda qui (contro le macro)
http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.5
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-38.4
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-38.5
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-38.6

a favore delle macro
http://www.idinews.com/macroPhobe.html
http://c2.com/cgi/wiki?PreprocessorsAreNotEvil


la fregatura principale la scoprirai quando dovrai utilizzare il debugger.

Bocos
09-05-2004, 21:53
vorrei farvi notare...

le direttive non hanno bisogno di punto e virgola gicche non sono istruzzioni da compilare , bensi è un commando al precompilatore.
il precompilatore esegue questi, che devono essere scritti su una riga
infatti se scrivete
#define x
y
quell y è fuori posto vi chiede dunque ; o altro.
il '\'posto prima di '\n'(nuova_linea) fa "skippare" nella traduzione del precompilatore l'effetto di '\n'.
provate dunque scrivere '\'' '(spazio)e poi '\n': il raggiro non funzia.
mi chiedevo '\''\n' == commento di n???
su C non esiste la scrittura \\ come commento ma le direttive funzionano separate da '\''\n'?

Cmq una piccolezza: ciascuno usa la sua tecnica,
io ho deciso e sprono chiunque a seguire il mio esempio a scrivere per esempio tutte le definizioni,costanti e macro in maiuscolo
quelle globali con la prima lettera in maiuscolo
le locali in minuscolo...
UTILITà?

le inline sono funzioni espanse esattamente come le macro
ma spesso nel lavoro di espansione di una macro può causare errori di compilazione o peggio errori di Run-time difficili da trovare

si usa quindi spesso su c++ il tipo inline con la bellezza di eliminare la chiamata a funzione ma la funzione c'è!
la macro viene completamente sostituita come testo!

la risoluzione di una inline avvolte è complessa (esempio un ciclo)...

MACRO vs INLINE:

#define QUADRATO(x) (x*x)//mettete al posto della x la variabile da elevare al quadrato

inline float Quadrato(float x){return (x*x);} //notare il return di funzione e ';'

{
float a,b;
int c,d;
/*...*/
b= QUADRATO(a); //compilato: b = (a * a) !!! sostituzione per testo
c= QUADRATO(d); //compilato: b = (a * a) !!! sostituzione per testo
}
l'inline ha un funzionamento simile a:
b = Quadrato(a); //b = { a * a }// in più a se definito intero il compilatore aggiunge un recast o vi fa notare

differenza : le macro sarebbero inaffidabili ofrono completa ottimizzazione,
le inline sono complesse da espandere e le ottimizzazioni che offrono variano da compilatore a compilatore...
forse questo per molti è già chiaro cmq rimane la mia domanda un po stolta visto che '\n' è un solo carattere... :bhò:
curioso però...

#define INVERSO(x) (1/x) //questo è un altro esempio
//con queste due macro non ho mai avuto problema nemmeno con classi, basti che siano definiti le operazioni (/ e *)...

aspetto risposte... ciao

/* Coder */
10-05-2004, 11:54
Originariamente inviato da internet
hai compilato con -O3 ?
se no, prova a compilarlo con questo flag e rifai i bench

per le macro guarda qui (contro le macro)
http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.5
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-38.4
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-38.5
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-38.6

a favore delle macro
http://www.idinews.com/macroPhobe.html
http://c2.com/cgi/wiki?PreprocessorsAreNotEvil


la fregatura principale la scoprirai quando dovrai utilizzare il debugger.

Si grazie, mi sono studiato i 4 evil.
Continuo comunque a preferire le macro, perkè inline non mi da certezze. Cioè se io dico "inline" al compilatore, non deve discutere, deve espandere in linea e basta, ciò non avviene.
Quando prima esamino bene tutti gli evil cases e cerco di rendere l'uso del mio costrutto privo della maggior parte di preoccupazioni.
E' chiaro che non riesco comunque a rendere una macro esattamente come una funzione inline in tutti i casi. Però alle funzioni macro uno le potrebbe dare un nome tutto maiuscolo in modo da allertare e far ricordare all'utilizzatore tutti gli evil prima di commettere sciocchezze.
Cmq così a prima vista penso che i 4 evil si possono risolvere in modo trasparente, quello però dove c'è l'esempio di macro safe e unsafe per ora non mi viene in mente nulla.

Quanto prima mi vedo ste cose e riuppo il tutto. Occorre stare attenti perkè ste macro sono carogne per i cosiddetti
"well-hidden-bugs" :D.

Per il fatto della debuggabilità penso di risolvere attraverso vie alternative, tanto il debugger io già lo uso poco per il fatto che faccio molto multi-process.

Grazie comunque dei link, avevo un sacco di fili scollegati in testa, adesso grazie a te circola corrente. :D

Ciao !

/* Coder */
10-05-2004, 13:00
Questo "dovrebbe" risolvere tutti gli evil in modo trasparente:



#define BEGIN (true?({ // Macro functions init syntax
#define END }):false) // Macro functions end syntax
#define RETURN // Macro functions return
#define VOID true // To be used for void returns

#define Fileno(fpStream) \
BEGIN \
int iRet; \
FILE* FpStReAm = fpStream; \
\
if((iRet = fileno(FpStReAm)) < 0) \
err_quit("(Module: %s) - ERROR fileno() failed\n", gargv[0]); \
\
RETURN iRet; \
END


Che ne pensate? riuscite a trovare qualche caso unsafe?

Ecco il nuovo bench senza ottimizzazione:



Istructions load: 100000000
Macros vs Inline
Getting times...

Inline: 2.040000 s
Macro: 1.640000 s


Fatemi sapere !

CIAO !!
:ciauz:

/* Coder */
10-05-2004, 14:48
Alla fine la cosa migliore è definirle inline e compilare ottimizzando così:



g++ -03 -Winline fileName.cpp


Se il compilatore non intende mettere inlinea una funzione, ci da un warning come per altro mi è già successo.
In quel caso si trasforma in macro come suddetto.
I benchmark con l'ottimizzatore a -03 danno gli stessi tempi con una precisione del centesimo di secondo.
Internet avevi ragione, ora va.


Conclusione:

Se non veniamo avvisati dal compialtore tramite -Winline è sempre meglio usare inline al posto di una macro :D.
Concordate?
Sarebbe bello ogni tanto darsi qualche regola fissa in questo mondo così pieno di dubbi e incertezze quale è la programmazione :stordita:.

Risolto il dilemma.

Ciao !
:ciauz:

Loading