Mattmmmmm
Mattmmmmm

Reputation: 189

The evaluation of logical expressions containing incrementation in C

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?

Upvotes: 2

Views: 147

Answers (3)

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

Upvotes: 5

anastaciu
anastaciu

Reputation: 23802

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.

Upvotes: 2

John Bode
John Bode

Reputation: 123468

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.

Upvotes: 1

Related Questions