macros w/o side effects (was Re: declarations in include files)
Jim Vlcek
vlcek at mit-caf.MIT.EDU
Tue May 16 02:36:55 AEST 1989
A short while ago, Jeffrey Percival (in <181 at larry.sal.wisc.edu>,
noted that if one relies upon header files for function declarations,
then one might later seamlessly change the function(s) into macros.
He asked if this interpretation was unflawed.
I pointed out, in <2337 at mit-caf>, that the macros might have problems
with arguments with side effects - the old ``square(++i)'' thing. I
made a mistake in there, by the way. I said:
``Any macro->function sleight of hand had best not take place behind
the scenes, and in fact should probably not take place at all.
Going the other direction is probably considered safe, although some
programs may have depended upon the side effects of the macro which
is now a function. Probably anyone who does so deserves to suffer,
though...''
That first line should read ``Any function->macro sleight of hand...''
Hopefully, this was clear already from the context.
Which brings us to Dan Bernstein, in <8420 at phoenix.princeton.edu>:
``Oh dear. I should be burned at the stake for some of the macros I write.
I even take functions like
sqaure(in,out) int in; int *out; { *out = in * in; }
and convert them into macros like
#define square(in,out) { int Tsquare1 = in; int *Tsquare2 = out;
*Tsquare2 = Tsquare1 * Tsquare1; }
``Gasp! Where's the error when I do square(i++,&result)? Where have the
side effects gone? How come this macro does exactly the same thing as
the function except that it's faster? And I would have thought from the
above article that this was impossible!''
OK, try this:
if (p>0)
square(p,&q);
else
q=0;
It'll work if square() is a function, but fail if square() is a macro
as you've defined. Can you find the syntax error? Further, as Dan
points out later, this is limited to functions or macros which do not
return a value, and hence is only a special case. It's for these
reasons that I never define any macros as compound statements.
Back to Dan:
``I have a tiny shell script that does the above conversion
automatically; I suppose it's being inefficient when a variable is
only used once (as in the above use of Tsquare2), but it basically
does the job right. There are no side effects, it's all perfectly
safe, and I don't think I deserve to suffer for it.''
My point about suffering was perhaps somewhat obscure. I said that it
was probably OK to change a macro into a function, although the
behavior could not be guaranteed to be identical in that the function
would evaluate its arguments only once, whereas the macro would
evaluate each argument as many times as it appeared. My point was
that anyone who depended upon the side effects ensuing from multiple
evaluations of a macro argument probably deserves to suffer. Perhaps
someone can show a reasonable counterexample, however.
Jim Vlcek (vlcek at caf.mit.edu uunet!mit-caf!vlcek)
More information about the Comp.lang.c
mailing list