Re: 'C' Operators precedence

Horst von Brand (
Thu, 21 May 1998 11:03:06 -0400

"Richard B. Johnson" <> 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

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                   
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