I came across a statement in the text C How to Program:
"Expressions with side effects (i.e., variable values are modified) should not be passed to a macro because macro arguments may be evaluated more than once.".
My question is what are expressions with side effects and why should they be not passed to a macro?
Side Effects can be defined as:
In addition to the initialization operation the value of y gets changed due to the side effect of ++ operator.
Now consider a macro for squaring of an integers :
You would expect the output to be
36 49
However the output is
36 64
because macro results in textual replacement and
res becomes (++a)*(++a) i.e, 8*8=64
Therefore we should not pass arguments with side effects to macros. (http://ideone.com/mMPQLP)
To put it simply a side effect is a write to an object or a read of a volatile object.
So an example of a side effect:
Here is a use of a side effect in a macro:
The danger is contrary to a function where the arguments are passed by value you are potentially modifying
b
object one or two times (depending on the macro arguments, here one time) in the macro because of the way macros work (by replacing theb++
tokens in the macro definition).The classic example is a macro to calculate the maximum of two value:
Now lets "call" the macro like this:
Now if
MAX
was a normal function, we would expect thatx
andy
would be incremented once, right? However because it's a macro the "call" is replaced like this:As you see, the variable
y
will be incremented twice, once in the condition and once as the end-result of the ternary operator.This is the result of an expression with side-effects (the post-increment expression) and a macro expansion.
On a related note, there are also other dangers with macros. For example lets take this simple macro:
Looks simple right? But now what if we use it like this:
That will expand like
And as you hopefully knows multiplication have higher precedence than addition, so the expression
a + b * 2
is equivalent toa + (b * 2)
, probably not what was intended by the macro writer. That is why arguments to macros should be put inside their own parentheses:Then the expansion will be
which is probably correct.