2

I just wrote a little program to help me get familiar with logical expression in C, and I was expecting the result to be:

1 
1 1 1
#include <stdio.h>

int main(void) 

{

    int I = 1, J = 1, K = 1;
    printf("%d\n", ++I || ++J && ++K);
    printf("%d %d %d", I, J ,K);

    return 0;
}

Instead, I got:

1 
2 1 1

The value of I was incremented by 1, and I have no idea why.

As far I have learned, I wasn't assigned(=) any new value in my program, so how was it value be changed?

Mattmmmmm
  • 155
  • 1
  • 6
  • `++I` increments `I`. Note that `&&` has greater precendence than `||` so the expression is evaluated as `++I || (++J && ++K)`. But because of the short-circuit rule, only the `++I` is evaluated and the expression must be `true` without needing to evaluate further. Beware of side-effects! – Weather Vane Mar 21 '20 at 14:59
  • @Weather Vane I thought that ```++J && ++K``` was evaluated first since && has higher precedence than || and the values of both of them had been incremented, apparently I was wrong – Mattmmmmm Mar 21 '20 at 15:06
  • It is evaluated from left to right, subject to precedence. The precedence means the expression is evaluated as `++I || (++J && ++K)` and not as `(++I || ++J) && ++K` – Weather Vane Mar 21 '20 at 15:07
  • @Mattmmmmm: precedence only affects grouping of operators and operands, it does not control order of evaluation. Both `&&` and `||` force left-to-right evaluation. – John Bode Mar 21 '20 at 17:16
  • The statements `I++;` and `I = I + 1;` have the exact same effect (incrementing `I`) but the sub-expressions have different values (assuming `I` has value `42` before the expression, the `I++` evaluates to `42`; `I = I + 1` evaluates to `43`). – pmg Mar 21 '20 at 17:27

3 Answers3

5

Your question addresses two separate issues.

The first one: Why is I incremented?

The second one: If the output is 2 1 1 and I was incremented why aren´t J and K incremented then too?


1.

Why is I incremented?

++ is the increment operator. It increments an operand by 1 count, analogous to the expressions i = i + 1 or i += 1, where i stands for the operand.

There is a difference between set ++ in front of (++i) or behind (i++) an operand. The answers under the following linked question address the difference at its best, so I won´t go too much in detail about this topic here since the difference is not crucial important at your provided code and I just wanted to annotate that circumstance for that you use the increment operator in your future programs properly and avoid further confusions.

C: What is the difference between ++i and i++?

Back to your code.

Since you use:

printf("%d\n", ++I || ++J && ++K);

I is immediately incremented by 1 inside the expression, so its value is actually 2, although this does not influence the logical evaluation because any value which is non-zero would be evaluated as 1/true as result of a logical condition test.

That´s why

printf("%d %d %d", I, J ,K);

prints 2 as the value of I.


2.

Why aren´t J and K incremented then too?

Logical testing evaluates from left to right. && has a higher precedence than ||. && combined expressions/sub-conditions need to be fulfilled together to be evaluated as true condition. As soon as a condition becomes true, which is the case with ++I, the evaluation of the remaining conditions is omitted since it is redundant.

That´s why J and K aren´t incremented by 1 with:

printf("%d\n", ++I || ++J && ++K);

but I is.

Thus, the correct output of

printf("%d %d %d", I, J ,K);

is:

2 1 1
Community
  • 1
  • 1
2

Looking at the expression

printf("%d\n", ++I || ++J && ++K);

++I || ++J && ++K is a logical expression, yes, but it's also incrementing all you variables, so they all should be 2 in the end of the expression and your output should be:

1 // true expression, I, J and K are all positive values
2 2 2

So why does this not happen?

Well, since I = 1, no more evaluations are needed, because the compiler knows that 1 || 0 && 0 is 1, (note that the evaluation is left to right and && has precedence over ||) this is the reason why ++J and ++K are not evaluated, and thus not incremented.

So, in the second printf you will have I = 2, J = 1 and K = 1.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
1

The expression ++I evaluates the current value of I plus 1; as a side effect, I is incremented.

Due to operator precedence rules, the expression ++I || ++J && ++K is parsed as ++I || (++J && ++K). Both || and && force left-to-right evaluation, so ++I is evaluated first.

Both || and && short-circuit - if the left-hand operand of ++I || ++J && ++K (++I) is non-zero, then the result of the expression is true (1) regardless of the value of the right-hand operand (++J && ++K), so the right hand operand isn’t evaluated at all.

If I starts out as -1, then ++I would evaluate to 0 (false) and then ++J && ++K would be evaluated. If the left-hand operand ++J evaluates to 0 (false), then the result of the expression is false regardless of the result of ++K, so ++K won’t be evaluated.

John Bode
  • 119,563
  • 19
  • 122
  • 198