Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!mit-eddie!mit-amt!mit-caf!vlcek From: vlcek@mit-caf.MIT.EDU (Jim Vlcek) Newsgroups: comp.lang.c Subject: Re: macros w/o side effects (was Re: declarations in include files) Message-ID: <2352@mit-caf.MIT.EDU> Date: 15 May 89 16:36:55 GMT References: <179@larry.sal.wisc.edu> <10251@smoke.BRL.MIL> <181@larry.sal.wisc.edu> <2337@mit-caf.MIT.EDU> <8420@phoenix.Princeton.EDU> Reply-To: vlcek@mit-caf.UUCP (Jim Vlcek) Distribution: usa Organization: Microsystems Technology Laboratories, MIT Lines: 67 A short while ago, Jeffrey Percival (in <181@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@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@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@caf.mit.edu uunet!mit-caf!vlcek)