macros w/o side effects (was Re: declarations in include files)

Dan Bernstein bernsten at phoenix.Princeton.EDU
Mon May 15 14:39:34 AEST 1989


In article <2337 at mit-caf.MIT.EDU> vlcek at mit-caf.UUCP (Jim Vlcek) writes:
> In article <181 at larry.sal.wisc.edu> jwp at larry.sal.wisc.edu.UUCP
> (Jeffrey W Percival) writes: 
  [if you rely upon .h files for function declarations,
   it is easy to later make a function into a macro]
> >Is that interpretation unflawed?
> If what was once a function is turned into a macro, programs which
> passed arguments with side effects to the function may not work
> correctly with the macro.  You know the tune:
> #define square(x) ((x)*(x))  /* Used to be a function ... needed speed */
> y = square(++i);
> 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...

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!

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.

Since C is not fully expression-based, it is impossible to do the above
conversion for functions that you're using as functions rather than as
procedures (i.e., functions that return a type and may not take up an
entire statement). One can to some extent use the comma operator, but
since one can't really declare local variables without { }, the results
can't be nested. However, any procedural function can be quite safely
converted into a macro.

What we really want here is a feature often observed to be missing from C:
inline functions. Inline functions need not be syntactically different
from normal functions; perhaps we could add an ``inline'' keyword to a
function declaration, with the restriction that the function must be
defined there (in the header file). A different approach would be to
make C fully expression-based, so that the comma operator would disappear
in favor of semicolons; the idea is to allow all possible statement
constructs as expression constructs. Of course, this must include local
variables.

---Dan Bernstein, bernsten at phoenix.princeton.edu



More information about the Comp.lang.c mailing list