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