6

I don't understand the output of the following program:

#include<stdio.h>

int main()
{
    int i=-3, j=2, k=0, m;
    m = ++i || ++j && ++k;
    printf("%d %d %d %d\n", i, j, k, m);
    return 0;
}

The output is -2 2 0 1 instead of -2 3 1 1, implying that ++i was evaluated (and caused the || operator to short-circuit its right hand side) before the expression ++j && ++k which appears to contradict the fact that the && operator has higher precedence than ||.

Would someone explain why?

martin
  • 3,149
  • 1
  • 24
  • 35
anurag
  • 11
  • 3
  • m is integer type I know the anwer... I need explaination why is k=0 – anurag Jul 30 '10 at 20:20
  • 4
    `j` and `k` are never incremented because that part of the expression is short-circuited. `++i` is true, so the rest of the expression is not evaluated. – Fred Larson Jul 30 '10 at 20:23
  • 1
    && has higher precedence,so why are j and k not incremented – anurag Jul 30 '10 at 20:24
  • 2
    I fixed up the question to reflect what OP was trying to ask (let's help him out here) and voted to reopen. – Amardeep AC9MF Jul 30 '10 at 20:30
  • 1
    I tried to improve the question further to make the source of the OP's confusion clearer, and replaced the title. I would have voted to reopen too, but it happened before I finished my edit. – RBerteig Jul 30 '10 at 20:43
  • It probably does not matter since writing such code is a really dumb idea - simply because the operator and sequence point rules are so arcane. It is 'smarter' (in terms of productivity) to avoid the dark corners than to waste time understanding them. – Clifford Jul 30 '10 at 20:51
  • @Clifford: in this case, I can't agree. Just for example, it's fairly common to see code that checks for a non-null pointer, then dereferences it: `if (x && x->whatever) ...`, and to understand why it works, you *need* to understand what `&&` means. – Jerry Coffin Jul 30 '10 at 20:55
  • 3
    @anurag: Since `&&` has higher precedence than `||`, `a || b && c` is parsed as `a || (b && c)`. The thing that may be confusing you is that `||` and `&&` short-circuit, so not all expressions need be evaluated. In this case, `++i` has a value of -2, which is true, so nothing on the right-hand side of `||` will be executed. – David Thornley Jul 30 '10 at 21:31
  • @Jerry Coffin: That was not what I was referring to, your example was clear and unambiguous and entirely legitimate and not at all like the expression used in this post. The problem of arcane precedence and *sequence point* rules does not apply in your example. The ill-advised usage I was referring to applies to the use of ++ and -- operators in an expression involving other operators. – Clifford Jul 31 '10 at 13:26
  • Er... Marked it as duplicate and only later realized that it was asked earlier than what I suggested instead. – AnT stands with Russia Aug 16 '14 at 06:45
  • @AndreyT There is another one: http://stackoverflow.com/questions/17239286 – martin Aug 16 '14 at 06:47
  • @martin: Yes, this is one of the most popular questions, which pops up again and again with remarkably similar wording and code. – AnT stands with Russia Aug 16 '14 at 06:54

4 Answers4

22

The output should be something like:

Error, line 2: 'm': undefined variable.

Edit: with that fixed, only the ++i should be evaluated. Precedence does not determine (or even affect) order of evaluation. Precedence means the expression is equivalent to ++i || (++j && ++k). Order of evaluation for || or && is always that the left operand is evaluated, then there's a sequence point. After the sequence point, the right operand is evaluated if and only if necessary to determine the final result (i.e., the right operand of || is evaluated if the left operand evaluated to zero; the right operand of && is evaluated if the left operand evaluated to non-zero).

In this expression, ++i is evaluated, then because it's the left operand of || and evaluated non-zero, none of the rest of the expression is evaluated.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
3

-2 2 0 1

Lazy.

#include <stdio.h>

int main()
{

 int i=-3,j=2,k=0;
 int m=++i||++j&&++k;

 printf("%d %d %d %d",i,j,k,m);

}

Compile, run and see for youself.

gcc tmp.c -o tmp
karlphillip
  • 92,053
  • 36
  • 243
  • 426
2

The expression:

++i || ++j && ++k

Is equivalent to:

(++i) || ((++j) && (++k))

Explaining:

  1. ++i is evaluated -- (-2) || ((++j) && (++k));
  2. The || operator is evaluated -- (1);

Since 1 || anything evalutes true, the right operand is not evaluated. Thus, the && precedence doesn't matter here. This short circuiting is guaranteed in both C and C++ by the relevant standards (see Is short-circuiting logical operators mandated? And evaluation order?).

Now, try using a sub-expression, like this:

(++i || ++j) && ++k

Which is equivalent to:

((++i) || (++j)) && (++k)

Explaining:

  1. ++i is evaluated -- ((-2) || (++j)) && (++k);
  2. || is evaluated -- (1) && (++k)
  3. ++k is evaluated -- (1) && (1);
  4. Evaluates true;
Community
  • 1
  • 1
jweyrich
  • 31,198
  • 5
  • 66
  • 97
0

By way of explanation:

#include <stdio.h>

int main()
{
    if (-1)
        printf ("-1!\n");
    else
        printf ("Not -1.\n");
    return 0;
}

Negative numbers are not false in C. Always compare boolean values to 0 (or FALSE) or you can get bitten by if (worked == TRUE) giving false negatives.

nmichaels
  • 49,466
  • 12
  • 107
  • 135