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