Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!rutgers!njin!princeton!phoenix!bernsten From: bernsten@phoenix.Princeton.EDU (Dan Bernstein) Newsgroups: comp.lang.c Subject: macros w/o side effects (was Re: declarations in include files) Summary: usually pretty easy Keywords: declarations include Message-ID: <8420@phoenix.Princeton.EDU> Date: 15 May 89 04:39:34 GMT References: <179@larry.sal.wisc.edu> <10251@smoke.BRL.MIL> <181@larry.sal.wisc.edu> <2337@mit-caf.MIT.EDU> Reply-To: bernsten@phoenix.Princeton.EDU (Dan Bernstein) Distribution: usa Organization: Hmph. Lines: 57 In article <2337@mit-caf.MIT.EDU> vlcek@mit-caf.UUCP (Jim Vlcek) writes: > In article <181@larry.sal.wisc.edu> jwp@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@phoenix.princeton.edu