I don't understand the output of this code:
long i=5, j=10;
if (++i || ++j) printf("%ld %ld\n", i, j);
else printf("Prog1\n");
The output is 6 and 10. I expected 6 and 11. Why wasn't j incremented?
The logical OR operator || is a short circut operator. That means that the right operand won't be evaluated if the result can be determined by looking only at the left operand.
Section 6.5.14 of the C standard regarding the Logical OR operator states the following:
4 Unlike the bitwise | operator, the || operator guarantees
left-to-right evaluation; if the second operand is evaluated, there is
a sequence point between the evaluations of the first and second
operands. If the first operand compares unequal to 0, the second
operand is not evaluated.
In this case, ++i is evaluated and the result is 6 (with the side effect of incrementing i. The logical OR operator evaluates to 1 (i.e. true) if either operand is non zero. Since the left side is non-zero, the right side is not evaluated, and subsequently j is not incremented.
Your if condition uses the short-circuited Logical OR operator ||. As the left side of the operator (++i) evaluates to true, the right side (++j) does not get executed.
Only ++i was executed in if statement because ++i is not zero and regarded already as true. Because of || OR operation, there's no need to execute ++j.
Related
I'm using C language, for the below code:
#include <stdio.h>
int main(int argc, char const *argv[])
{
int num1=0;
int res = ++num1 && num1++;
printf("%d\t%d\n",num1,res);
}
In the above code I get output as 2 1. I think the output should be 2 0.
Please correct me if wrong, to solve this statement, the num1++(0) would be executed first due to highest precedence and then ++num1(2) would be executed and then at last && will be preformed because it has the lowest precedence.
Please comment how is this statement getting executed.
In some of the tutorials I find that postfix ++ and prefix ++ have the same precedence, but if that is true then according to the associativity rule again num1++ should be executed first(right to left) which should again lead to answer as 2 0.
In the expression used as an initializer
int res = ++num1 && num1++;
there is a sequence point for the operator &&.
From the C Standard (6.5.13 Logical AND operator)
3 The && operator shall yield 1 if both of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
and
4 Unlike the bitwise binary & operator, the && operator guarantees
left-to-right evaluation; if the second operand is evaluated, there is
a sequence point between the evaluations of the first and second
operands. If the first operand compares equal to 0, the second operand
is not evaluated.
At first the left operand of the operator is evaluated and as a result num1 will be equal to 1 due to the unary (prefix) increment operator. As the sub-expression is not equal to 0 then the second operand is evaluated. Its value is the value before incrementing that is 1. As this second operand is also unequal to 0 then the whole expression is evaluated to the logical true and its value is 1 (see the first quote from the C Standard).
This value 1 is assigned to the variable res while the variable num1 after the postfix increment will be equal to 2.
So you will have that after this declaration res is equal to 1 and num1 is equal to 2.
Lots of misconceptions here. First of all, operator precedence states the order of parsing, not the order of execution. There are two related but different terms, operator precedence and order of evaluation.
See What is the difference between operator precedence and order of evaluation?.
Once you understand order of evaluation, the && operator specifically comes with well-defined sequencing, which isn't normally the case for C operators. It guarantees a left-to-right order of evaluation. C17 6.5.14/4:
Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; if the
second operand is evaluated, there is a sequence point between the evaluations of the first
and second operands. If the first operand compares unequal to 0, the second operand is
not evaluated.
Normally, you wouldn't be able to wild and crazy things with the ++ operator mixed with other operators, but the above && rule makes it possible in this specific case.
See Why can't we mix increment operators like i++ with other operators? It explains sequencing/sequence points.
In some of the tutorials I find that postfix ++ and prefix ++ have the same precedence,
They don't, prefix ++ takes precedence over postfix (and other unary operators). So associativity does not apply.
Please correct me if wrong, to solve this statement, the num1++(0) would be executed first due to highest precedence and then ++num1(2) would be executed and then at last && will be preformed because it has the lowest precedence.
Precedence only controls which operators are grouped with which operands - it does not affect the order in which expressions are evaluated.
The &&, ||, ?:, and comma operator all force left-to-right evaluation - the left operand is fully evaluated (and any side effects applied) before the right operand. && and || both short circuit - for &&, the right operand will be evaluated only if the left operand is non-zero.
The unary (prefix) ++ operator yields the current value of the operand plus 1, so the result of ++num1 is 1. As a side effect the value in num1 is incremented. Since this result is non-zero, num1++ is also evaluated. The postfix ++ operator yields the current value of the operand, so the result of num1++ is 1. As a side effect the value in num1 is incremented.
The result of an && expression is 1 if both operands are non-zero, 0 otherwise.
It's roughly equivalent to writing
tmp = num1 + 1;
num1 = num1 + 1;
res = 0;
if ( tmp != 0 )
{
if ( num1 != 0 )
{
res = 1;
}
}
num1 = num1 + 1;
So the result of ++num1 && num1++ is 1, and the value stored in num1 at the end of it is 2.
In some of the tutorials I find that postfix ++ and prefix ++ have the same precedence,
That is very wrong and you should stop using those tutorials immediately. Postfix operators have higher precedence than unary operators - *a++ is parsed as *(a++), ++a[i] is parsed as ++(a[i]), etc. An expression like ++i++ would be parsed as ++(i++), but you can't write such an expression in C - the result of i++ isn't an lvalue and cannot be the operand of a unary ++ like that.
Can anybody explain why the output is 'a' only, if && has higher priority than ||. Below is the code snippet.
#include<stdio.h>
int main(){
int a = printf("a")||printf("b")&&printf("c");
return 0;
}
This is a feature called "Short Circuit Evaluation".
The code is trying to determine if the expression X || Y && Z is True or False so it can assign a value to variable a.
Because of short-circuit evaluation, once the first part, printf("a"), is True (non-zero), it does not matter what the 2nd half of the expression is, so it does not get evaluated.
True || (*anything*) will result in true, so why bother evaluating the 2nd half of the code?
The entire 2nd part of the expression: printf("b")&&printf("c") gets skipped completely, because its not needed.
As your code demonstrates very well, when part of an expression is skipped due to Short Circuiting, any side-effects of that code (such as printing to the console) get skipped as well, sometimes leading to confusing and non-obvious bugs.
Not all languages have short-circuit evaluation, but it is commonly found in most languages.
&& has higher precedence, according to conventional terminology. "Priority" gives a potentially (more) misleading impression.
Whatever you call it, it is not about order of operations, but rather about correctly identifying the operands of each operator. That && has higher precedence means that your declaration of a is equivalent to
int a = printf("a") || (printf("b")&&printf("c")); // THIS
, as opposed to
int a = (printf("a")||(printf("b")) && printf("c"); // NOT THIS
Furthermore, the printf("a") is executed first either way, because the left-hand operand of && and || is always evaluated before the right-hand one, and the right-hand operand is only evaluated at all if that is necessary to determine the result of the operation.
In your case, each printf call will return 1 on success (if it is executed at all). The printf("a") is executed first, per the rule for the operands of an || operator. Its result is enough to determine the overall result of that operation, so no part of the other operand is evaluated.
If you used parentheses to override the default grouping then the short-circuiting would be more narrowly scoped, with the result that ac would be printed.
Precedence only affects which operators are grouped with which operands, not the order in which subexpressions are evaluated.
Both && and || force left-to-right evaluation. Due to precedence rules, the expression x || y && z is parsed as x || (y && z), however it is evaluated as follows:
x is evaluated and all side effects are applied;
if x evaluates to 0, then
y is evaluated and all side effects applied
if y evaluates to non-zero, then
z is evaluated
if z is non-zero, then
the result of y && z is 1, and
the result of x || y && z is 1
else
fhe result of y && z is 0, and
the result of x || y && z is 0
end if
else
z is *not* evaluated
the result of y && z is 0, and
the result of x || y && z is 0
end if
else
y && z is *not* evaluated
x || y && z evaluates to 1
end if
Remember that both && and || short-circuit - depending on the value of the left operand, the right operand will not be evaluated. If a is 0, then a && b evaluates to 0 regardless of the value of b, so b is not evaluated at all.
Similarly, if a is non-zero, then a || b evaluates to 1 regardless of the value of b, so b is not evaluated.
1) Sequence Point
A sequence point defines any point in a computer program's execution
at which it is guaranteed that all side effects of previous
evaluations will have been performed, and no side effects from
subsequent evaluations have yet been performed.
At a sequence point, it is guaranteed that evaluation of all previous sub-expressions are complete.
2) From Microsoft article:
Only the sequential-evaluation (,), logical-AND (&&), logical-OR (||),
conditional-expression (? :), and function-call operators constitute
sequence points, and therefore guarantee a particular order of
evaluation for their operands.
So, there exists a sequence point between left operand and right operand of logical OR || and logical AND &&. Hence, logical operators guarantee evaluation of their operands from left to right.
3) From C Sequence Points
The left operand of the
logical-AND operator is completely evaluated and all side effects
complete before continuing. If the left operand evaluates to false
(0), the other operand is not evaluated.
The left operand of the
logical-OR operator is completely evaluated and all side effects
complete before continuing. If the left operand evaluates to true
(nonzero), the other operand is not evaluated.
4) Reason:
int a = printf("a") || printf("b") && printf("c");
So, there is a sequence point between printf("a") and (printf("b") && printf("c")).
That's why first printf("a") is evaluated. Since, the left operand result is non-zero, the right operand is not evaluated (short-circuit evaluation).
printf() is a function that always returns the number of written characters (for printf("a"); it returns 1).
The logical operators (|| and &&) in C evaluate their arguments from left to right in a way that they cut the evaluation at the point on which there's security on the final result. As the first argument to || is true (because 1 is different than 0), the right operand to || doesn't need to be evaluated, as the result will be true anyway, and this is why the right expression (printf("b") && printf("c")) is not evaluated at all.
For || if the left operand evaluation gives true, there's no need to evaluate the right argument. For && if the left operand evaluates false, then the result will be false, and there's no need to evaluate the right argument.
In the following code, I am getting 10 | 1 | 1 as a result. But according to precedence rules shouldn't 'and' operator must be evaluated first?(and yield c=9) Like : d = a || (--b)&&(--c) since 'and' has higher precedence. ( or shortcutting breaks precedence rules ?)Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
int main(){
int a,b,c,d;
a =1;
b = c = 10;
d = a|| --b&&--c;
printf("%d\n",c);
printf("%d\n",a);
printf("%d\n",d);
return 0;
}
Precedence and order of evaluation are two different things. From Logical OR
documentation (emphasis mine):
There is a sequence point after the evaluation of lhs. If the result of lhs compares unequal to zero, then rhs is not evaluated at all (so-called short-circuit evaluation).
In case of exp1 || exp2, exp1 is always evaluated first as there is a sequence point after it and if exp1 is non-zero then exp2 is not evaluated.
Precedence only determines which operands are grouped with which operators - it does not control the order in which expressions are evaluated.
In your example, it means the expression is parsed as
a || (––b && ––c)
Both || and && force left-to-right evaluation1. Both introduce a sequence point (IOW, the left hand operand will be evaluated and all side effects will be applied before the right hand operand is evaluated).
Both operators short-circuit - if the left operand of || evaluates to non-zero, then the result of the expression is 1 (true) regardless of the value of the right operand, so the right operand isn’t evaluated at all. If the left operand of && is 0, then the result of the expression is 0 (false) regardless of the value of the right operand, so the right operand isn’t evaluated at all.
In your expression, a is evaluated first. It has a non-zero value (1), so ––b && ––c is not evaluated.
Along with the ?: and comma operators. All other operators (arithmetic, equality, subscript, etc.) do not force a particular order of evaluation.
#include<stdio.h>
int main()
{
int i=-1, j=-1, k=-1, l=2, m;
m = (i++ && j++ && k++) || (l++);
printf("%d %d %d %d %d", i, j, k, l, m);
}
I am having confusions about how operator precedence is working in the evaluation of the logical expression in the given program.
The variable m will be assigned 0 or 1 depending on the value of the logical expression that follows it.
The first parenthesis will be evaluated and the overall result of two AND operations will be true or 1. But, since a short-circuit logical OR is used, the second parenthesis is not getting evaluated.
So, my question is if parentheses have higher precedence that all the other operators in that expression, why is not both the parentheses evaluated first, and then the OR operation performed?
That is, why is the output 0 0 0 2 1 and not 0 0 0 3 1?
EDIT:
What I have asked is somewhat different from this (suggested duplicate)
as I am emphasizing on the parentheses enclosing the second operand of OR operator.
Operator precedence comes into effect when there's an ambiguity.
In this case, the spec is quite clear.
The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it
yields 0. The result has type int.
and, (emphasis mine)
Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; if the
second operand is evaluated, there is a sequence point between the evaluations of the first
and second operands. If the first operand compares unequal to 0, the second operand is
not evaluated.
In your case,
(i++ && j++ && k++) || (l++);
(i++ && j++ && k++) is the left operand and (l++); is the right operand and the rest should be quite clear. :)
Operator precedence (and associativity) only determines how the expression should be parsed. It is a common mistake to confuse it with order of evaluation of the operands, which is different thing. Operator precedence is rather irrelevant in this example.
For most operators in C, the order of evaluation of the operands is not specified. Had you written true | l++ then l++ would have been executed. The "short-circuit evaluation" is the reason why this doesn't happen in your code. The && || operators is a special case, since they explicitly define the order of evaluation. The right operand of || is guaranteed not to be evaluated in case the left operand evaluates to non-zero.
This post-increment operator usage is confusing.
{int a=0,b=1,c=2,d;
d=a++||b++||c++
printf("%d %d %d %d",a,b,c,d);}
output is
1,2,2,1
value of c did not increase but if I replace it with && operator it increases. Why?
Quoting C11, chapter §6.5.14, (emphasis mine)
Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; if the
second operand is evaluated, there is a sequence point between the evaluations of the first
and second operands. If the first operand compares unequal to 0, the second operand is
not evaluated.
So, in your case,
d=a++||b++||c++
is the same as
d= ( (a++ || b++) || c++)
Then, the statement inside the first parenthesis is evaluated, first a++ (post-increment) evaluates to 0 (side-effect pending), so the RHS of the first || is evaluated, b++, producing 1 and the result of the || operation is TRUE, yields 1.
That result, 1, is the LHS of the second ||. Hence, the RHS of the second || (c++) is not evaluated anymore and the final result becomes TRUE, again yielding 1, which gets stored in d.
So, finally,
a++ is evaluated, becomes 1
b++ is evaluated, becomes 2
c++ is not evaluated, remains 2
the result of || is stored in d, that is TRUE, so stores 1.
On the other hand, for logical AND && operator,
[...] If the first operand compares equal to 0, the second
operand is not evaluated.
So, if you replace the last || with &&, then for the outer statement, the LHS becomes 1 and the RHS evaluates, making c++ to be evaluated and incremented, as a side effect.