0
#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?

mpromonet
  • 11,326
  • 43
  • 62
  • 91
  • `k==MAX(i++,++j);` isn't even right with the double `==` – Weather Vane Jan 07 '16 at 19:28
  • 2
    @FUZxxl This code is not undefined. – 2501 Jan 07 '16 at 19:33
  • @2501 It is. There is no sequence point between the `(x)>(y)` and the `(x)`. – fuz Jan 07 '16 at 19:34
  • 1
    @FUZxxl Yes there is. *C11:6.5.15, p4.* – 2501 Jan 07 '16 at 19:35
  • I don't even understand what is the point of finding a max of something that might no longer be the max. The question should have been shot in the foot, especially since it does not even print the max. – Weather Vane Jan 07 '16 at 19:36
  • 1
    @abhaynanda so a macro named `MAX`, which finds the maximum of two given numbers, has nothing to do with finding the maximum of the given numbers? – Weather Vane Jan 07 '16 at 19:43
  • 1
    "There is no sequence point between the (x)>(y) and the (x)" -- Yet another obviously incorrect answer that indicates both poor knowledge of C and failure to do research. – Jim Balter Jan 08 '16 at 07:54
  • "Why the output is 11 7 0 instead of 11 6 0?" -- Why should it be "11 6 0"? It compares `i++` to `++j` and yields either `i++` or `++j` (in this case the latter, as explained in David Hefferman's answer) ... that sure looks like a total of three increments to me. It would really help if people who ask these sorts of "why isn't the result xyz?" questions would say why they expect that result. – Jim Balter Jan 08 '16 at 07:58

4 Answers4

2

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);
        ^
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 2
    `k==(i++) > (++j)` I think the 2nd part `(i++) > (++j)` is evaluated first because `>` is higher precedence than `==` – artm Jan 07 '16 at 19:49
  • @artm Yes you are correct. Thank you. I have edited. – David Heffernan Jan 08 '16 at 07:34
  • Someone downvoted an accepted answer without explanation? I'll throw in a +1 to counter. – Jim Balter Jan 08 '16 at 08:00
  • @Jim The downvotes were quite valid before I made my latest edit. I think my answer was accepted in error. Given that I could not delete it after acceptance, I had to fix it. Thanks! – David Heffernan Jan 08 '16 at 08:02
  • Downvotes are for completely wrong and misleading answers. Your error about precedence is worthy of pointing it out, not of a downvote. You won't see those downvoters coming back to remove them now that you have made the correction. And several other answers here, including your first one that you've deleted, received unwarranted downvotes. – Jim Balter Jan 08 '16 at 08:16
  • @Jim The voting prompted me to come back and check again and realise my error, and fix it. I think that's good. Sure the voters are not likely to return. I should have got it right first time! The system works I think. – David Heffernan Jan 08 '16 at 08:20
  • "The voting prompted me to come back " -- A comment would have the same effect, wouldn't it? In fact, without artm's comment, you wouldn't know what error you had made. "I should have got it right first time!" -- I can't make much sense of that. Of course one should *try* to get it right the first time, and I imagine you did. We all make mistakes. Anyway, we have a different view of this and that's ok ... but it's amusing which side of it you're taking. :-) – Jim Balter Jan 08 '16 at 08:25
  • 1
    @Jim The first time I read that comment I didn't take it in at all. But it got up votes, I got down votes and that helped me ask myself again if I had got it right. I think the voting was helpful. Maybe I should have tried harder to understand the comment originally. – David Heffernan Jan 08 '16 at 08:30
  • Well, as long as you came out a better person for it. :-) Your self-criticism is admirable. Over and out. – Jim Balter Jan 08 '16 at 08:34
  • ok one downvote was from me, I fixed it after the edit - thanks – artm Feb 03 '16 at 11:35
1

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

2501
  • 25,460
  • 4
  • 47
  • 87
0

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.
artm
  • 17,291
  • 6
  • 38
  • 54
-2

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.

  • 1
    It tells him clearly that substitutions are carried out literally, a key point thats being overlooked. – Shoaib Hussain Jan 07 '16 at 20:12
  • This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post - you can always comment on your own posts, and once you have sufficient [reputation](http://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](http://stackoverflow.com/help/privileges/comment). - [From Review](/review/low-quality-posts/10813833) – Uyghur Lives Matter Jan 08 '16 at 20:35
  • My comment was in response to an earlier comment which seems to have been deleted to by the user. There was no clarification requested from the author anywhere in the post. – Shoaib Hussain Jan 08 '16 at 21:46