abhay nanda
abhay nanda

Reputation: 47

Macro Substitution assignment

#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

Answers (4)

David Heffernan
David Heffernan

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:

  1. Your main is declared incorrectly. It should be int main(void).
  2. If you compile with warnings enabled the compiler will flag the line in question. My compiler says:
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

2501
2501

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

Shoaib Hussain
Shoaib Hussain

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

tdao
tdao

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).
  • Because 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

Related Questions