Messages in this thread | | | Subject | Re: 'C' Operators precedence | Date | Thu, 21 May 1998 11:03:06 -0400 | From | Horst von Brand <> |
| |
"Richard B. Johnson" <root@chaos.analogic.com> said:
[...]
> Sigh. It has nothing to do with clobbering registers. It has to do with > the fact that the function(s) and/or macros, anything that closes (), will > all be 'evaluated' first. To evaluate a function, requires that any > parameters passed to the function be stabilized by a sequence-point, and > the function be called. To evaluate a macro, requires only that it be > expanded as text. However, the () for passed parameters to a macro, if > it exists, requires that the contents of () be evaluated before the > macro is expanded, because () has the highest presedence of any 'C' > operator.
Macros are just expanded as text, no evaluation takes place. The ()'s are long gone when the code is compiled:
#define mulx(x) x *
add(3 + 4) 17
gives (pure text manipulation!):
3 + 4 * 17
No "3 + 4" evaluation has taken place, and the result is certainly way different from what your rule of thumb says. This is exactly one of the main reasons C++ introduced inline functions: Macros just manipulate text, the C preprocessor (or whatever does its job, it doesn't need to be a separate program) has no idea whatsoever of C syntax or semantics. Witness imake(1), it (ab)uses cpp to create Makefiles by #including and #defining stuff, taking the Imakefile as a "C source".
> #include <stdio.h> > > static int a, b, c, d, e; > static int f() > { > return a; > } > int main() > { > b = 1; > c = 2; > d = 3; > e = 4; > printf("%d\n", f() + b + c + d + e ); > printf("%d\n", b + f() + c + d + e ); > printf("%d\n", b + c + f() + d + e ); > printf("%d\n", b + c + d + e + f() ); > return 0; > > }
> Compile this with -S. > This will show that the function is always called first, regardless > of where it is first seen by the compiler. It must do this because > of the reasons previously stated.
It has no obligation whatsoever to do that, it's just that on a regular machine registers have to be saved and restored someplace (either in the caller or the callee). If the caller saves them, not placing stuff unnecesarily into registers before the call means there is less stuff that has to be saved and restored, i.e., less overall work to be done. If the compiler wanted, it might even compute a + b, c + d and f() in paralell, and then compute (a +b) + (c + d) and f() + e in paralell, and finally compute ((a + b) + (c + d)) + (f() + e). No, this is not ridiculous: On some machines, like the IBM/370, the best order to compute certain expressions involves computing part of one operand and part of the other interleaved.
Besides, the output of one particular compiler can only show what that particular compiler chooses to do in that particular case, not what every compiler has to do in all possible cases.
Can we take this discussion to news:comp.lang.c? It has nothing to do with the linux kernel -- Horst von Brand vonbrand@sleipnir.valparaiso.cl Casilla 9G, Viña del Mar, Chile +56 32 672616
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu
| |