Reputation: 47
#define MAX(x,y)(x)>(y)?(x):(y)
main()
{
int i=10,j=5,k=0;
k==MAX(i++,++j);
printf("%d %d %d",i,j,k);//11 7 0
}
Why the output is 11 7 0 instead of 11 6 0?
Upvotes: 0
Views: 132
Reputation: 613262
The statement expands to
k==(i++)>(++j)?(i++):(++j)
Let's re-write this with some added parens to emphasise how the expression is parsed when accounting for precedence rules:
( k == ( (i++) > (++j) ) ) ? (i++) : (++j)
Note that >
has higher precedence than ==
.
Now, (i++) > (++j)
is evaluated first, it evaluates to 1
and both i
and j
are incremented. Then k
is compared for equality with 1
and that yields 0
. The conditional operator thus evaluates to (++j)
and so j
is incremented one more time.
In total i
is incremented once, j
is incremented twice and k
is not modified. And hence the output is as you describe.
This is a good example of the perils of using macros. A function is really what you need.
Some other points:
main
is declared incorrectly. It should be int main(void)
.C:\Users\blah\Desktop>gcc main.c -Wall -o main.exe main.c: In function 'main': main.c:2:20: warning: suggest parentheses around comparison in operand of '==' [-Wparentheses] #define MAX(x,y)(x)>(y)?(x):(y) ^ main.c:6:8: note: in expansion of macro 'MAX' k==MAX(i++,++j); ^
Upvotes: 2
Reputation: 25753
The macro is replaced by the ternary operator by the preprocessor:
k == (x) > (y) ? (x) : (y)
The comparison: (x)>(y)
will be done first and will yield 1, but then the rest of the ternary operator will not be evaluated just yet, because operator ==
has precedence. The code is equivalent to:
( k == ( (x) > (y) ) ) ? (x) : (y)
We have to compare that result (which was 1) to k: k==(x)>(y)
, which will yield the result 0. Then only the third operator of the ternary operator will be evaluated: (y)
.
All in all, i
will be evaluated once, and j
twice. So the final result is 11 for i
and 7 for j
. (Variable k
will stay 0 as it was never assigned a value.)
Upvotes: 1
Reputation: 95
Macros are where you need to be careful when defining them, they do not necessarily expand the way you expect them to. A key feature of macros in C is that they literally carry out substitution, term for term.
This concept is well explained in the K&R book, as well as in multiple tutorials online, just google it.
Upvotes: -2
Reputation: 17678
Expand the macro with real expression:
k == (i++) > (++j) ? (i++) : (++j);
expr1 ? expr2 : expr3;
This is a typical conditional expression.
expr1
is k == (i++) > (++j)
. This actually contains two logic operations here. Because ==
has lower precedence than >
, then this logic (i++) > (++j)
is evaluated first, and ++j
is done BEFORE the first logic test. j
now is 6, and we have 10 > 6
which is true (1
). Now come to the second logic k == 1
which evaluated to false (0
).expr1
is false, expr3
is evaluated, ie (++j)
and again the ++ post-fix means that j
is incremented BEFORE the evaluation. j
now becomes 7.Upvotes: 0