Macro al posto di una funzione

P

pozz

Ciao a tutti,

in alcuni casi le funzioni in C sono così semplici che è meglio
definirle come delle macro. Per evitare che l'utilizzatore si
accorga di usare una macro o una funzione, avevo pensato di
scrivere la macro in questo modo:

#define mul(x,y) {x*y;}

In questo modo, chiunque utilizzi la mia macro potrà scrivere
semplicemente:
mul(x,y);
come se fosse una semplice funzione.
Però, se devo scrivere:
if( x>0 )
mul(x,y);
else
mul(-x,y);
....il compilatore mi dà giustamente errore. Il problema di sintassi
si risolve mettendo le parentesi graffe ai due rami dell'if, ma
normalmente queste non sono obbligatorie.

Esiste un modo più elegante per fare quello che voglio?
 
P

pozz

pozz said:
Ciao a tutti,

Oooops, I believed posting in an italian group, excuse me.

My question is:
when I define a function as a macro I use:
#define mul(x,y) {x*y;}
So the programmer can use the macro as it was a function, such as:
mul(x,y);

But, when there is an "if" statement as in:
if( x>0 )
mux(x,y);
else
mux(-x,y);
the compiler exits with error. It's right and I resolve the problem
using {} in the "if" branches. Is there an elegant way to define a
function as a macro without problems in "if" statement?
 
J

Joona I Palaste

pozz said:
Ciao a tutti,
in alcuni casi le funzioni in C sono così semplici che è meglio
definirle come delle macro. Per evitare che l'utilizzatore si
accorga di usare una macro o una funzione, avevo pensato di
scrivere la macro in questo modo:
#define mul(x,y) {x*y;}
In questo modo, chiunque utilizzi la mia macro potrà scrivere
semplicemente:
mul(x,y);
come se fosse una semplice funzione.
Però, se devo scrivere:
if( x>0 )
mul(x,y);
else
mul(-x,y);
...il compilatore mi dà giustamente errore. Il problema di sintassi
si risolve mettendo le parentesi graffe ai due rami dell'if, ma
normalmente queste non sono obbligatorie.
Esiste un modo più elegante per fare quello che voglio?

In vostro programmo, il preprocessor transforma il texto por questo:

if( x>0 )
{x*y;};
else
{-x*y;};

Questo e un error, que il "else" non ha un "if" por attachi in.

Scriver vostro macro como questo:

#define mul(x,y) ((x)*(y))

e vostro programmo functionera.
 
C

CBFalconer

pozz said:
My question is:
when I define a function as a macro I use:
#define mul(x,y) {x*y;}
So the programmer can use the macro as it was a function, such as:
mul(x,y);

But, when there is an "if" statement as in:
if( x>0 )
mux(x,y);
else
mux(-x,y);
the compiler exits with error. It's right and I resolve the problem
using {} in the "if" branches. Is there an elegant way to define a
function as a macro without problems in "if" statement?

Try (only parentheses, no braces):

#define mul(x, y) ((x) * (y))

Then you can safely write:

if (x >= 0) z = mul( x, y);
else z = mul(-x, y);
 
R

Richard Bos

BTW, it is good practice to give macros all-capital names, so they can
be distinguished from real functions; this is important, because some
macros can evaluate their arguments more than once. For example,

#define DOUBLE(x) ((x)+(x))
int double(int x)
{
return x+x;
}
int a,b;

a=DOUBLE(4); /* a is 8; valid. */
a=double(4); /* Ditto. */
b=double(a++); /* b is 16; a is now 9. Also valid. */
b=DOUBLE(a++); /* Oops... */

The final line is not OK, because it is preprocessed to

b=((a++)+(a++));

which modifies a twice between sequence points, giving undefined
behaviour. Thus, you can pass arguments with side effects to functions,
but you're not guaranteed that you can do so to macros. Hence the
importance of knowing which function-like calls are macros.
Try (only parentheses, no braces):

#define mul(x, y) ((x) * (y))

And when your macro gets too complicated for that, try
<http://www.eskimo.com/~scs/C-faq/q10.4.html>.

Richard
 
M

Mark McIntyre

BTW, it is good practice to give macros all-capital names, so they can
be distinguished from real functions; this is important, because some
macros can evaluate their arguments more than once. [/QUOTE]

Its also a good idea to use extra parens, for simlar reasons.
For example consider what
mul(4+5, 5);
evaluates to.

I'm also slightly puzzled at your macro. Its not strictly a function-like
macro since it doesn't return a value. You also can't use it in an
assignment.
This oddity by the way is probably causing your error. If you expand out
your macro when used in the if() statement, you'll see that.
The way to define function-like macros is
#define MUL(a,b) ((a) * (b))
You can then use MUL as a true function.
 
C

CBFalconer

Mark said:
BTW, it is good practice to give macros all-capital names, so they can
be distinguished from real functions; this is important, because some
macros can evaluate their arguments more than once.

Its also a good idea to use extra parens, for simlar reasons.
For example consider what
mul(4+5, 5);
evaluates to.

I'm also slightly puzzled at your macro. Its not strictly a function-like
macro since it doesn't return a value. You also can't use it in an
assignment.
This oddity by the way is probably causing your error. If you expand out
your macro when used in the if() statement, you'll see that.
The way to define function-like macros is
#define MUL(a,b) ((a) * (b))
You can then use MUL as a true function.[/QUOTE]

Mark, there is nothing there that I wrote. Please edit the
attributes to match the portion quoted after snipping. I have
left your entire article unsnipped to illustrate the point.
 
P

pozz

Ok, and what if I want to include more C-instructions in a single macro?
For example:
#define FOO(x,y) (x++;y*=2;)

That's an error, so I can write:
#define FOO(x,y) x++;y*=2;
But if I write:
while( x<100 )
FOO(x,y);
the program is different than what it should be. The y*=2; instruction
will be executed only once after exiting from while() but I want to
execute it inside the while().
 
M

Mark McIntyre

Mark, there is nothing there that I wrote. Please edit the
attributes to match the portion quoted after snipping. I have
left your entire article unsnipped to illustrate the point.

Chuck, apologies if this sounds rude, but I'm not going to trawl through
all the attributions of every post I reply to, just to make sure some
remark by some attribution line remains in. I'm happy to make reasonable
efforts, of course.
In this case it seems (to me) that Richard snipped what you said.
 
R

Richard Bos

Mark McIntyre said:
Chuck, apologies if this sounds rude, but I'm not going to trawl through
all the attributions of every post I reply to, just to make sure some
remark by some attribution line remains in. I'm happy to make reasonable
efforts, of course.
In this case it seems (to me) that Richard snipped what you said.

Erm... no. Only in the bit you quoted; not in the entire post.

Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top