As I know logical operator &&
has higher precedence than ||
. On running the code:
#include <stdio.h>
int main()
{
int i = 1, j =1, k = 1;
printf("%d\n",++i || ++j && ++k);
printf("%d %d %d",i,j,k);
return 0;
}
is giving the output:
1
2 1 1
which is possible only when ++i || ++j && ++k
is evaluated like this:
(++i) || (++j && ++k)
But, according to operator precedence rule it should be evaluated as:
(++i || ++j) && (++k)
and hence output should be:
1
2 1 2
What is going wrong with this?
NOTE: As per my understanding I think an operator of higher precedence evaluated as follows(if it is left associative):
1. Evaluate its left expression
2. Then evaluate its right expression(if needed)
Am I wrong?
1) What is the Priority among (*, /, %), (+, -) and (=) C Operators.? Explanation: Assignment operator in C has the least priority.
The precedence of an operator specifies how "tightly" it binds two expressions together. For example, in the expression 1 + 5 * 3 , the answer is 16 and not 18 because the multiplication ("*") operator has a higher precedence than the addition ("+") operator. Parentheses may be used to force precedence, if necessary.
The logical-AND operator ( && ) has higher precedence than the logical-OR operator ( || ), so q && r is grouped as an operand. Since the logical operators guarantee evaluation of operands from left to right, q && r is evaluated before s-- .
The precedence of operators determines which operator is executed first if there is more than one operator in an expression. Let us consider an example: int x = 5 - 17* 6; In C, the precedence of * is higher than - and = . Hence, 17 * 6 is evaluated first.
Firstly, as you said it yourself, &&
has higher precedence, which means that operand grouping should be
(++i) || (++j && ++k)
Why you are saying that "according to operator precedence" it should be (++i || ++j) && (++k)
is not clear to me. That just contradicts what you said yourself.
Secondly, operator precedence has absolutely nothing to do with order of evaluation. Operator precedence dictates the grouping between operators and their operands (i.e. operator precedence says which operand belongs to which operator).
Meanwhile, order of evaluation is a completely different story. It either remains undefined or defined by completely different set of rules. In case of ||
and &&
operators the order of evaluation is indeed defined as left-to-right (with mandatory early completion whenever possible).
So, operator precedence rules tell you that the grouping should be
(++i) || ((++j) && (++k))
Now, order-of-evaluation rules tell you that first we evaluate ++i
, then (if necessary) we evaluate ++j
, then (if necessary) we evaluate ++k
, then we evaluate &&
and finally we evaluate ||
.
You say:
which is possible only when
++i || ++j && ++k
is evaluated like this:(++i) || (++j && ++k)
But, according to operator precedence rule it should be evaluated as:
(++i || ++j) && (++k)
The first grouping is correct because the precedence of &&
is higher than the precedence of ||
. Then the expression as a whole evaluates the LHS of the ||
, with the side-effect of incrementing i
, which evaluates to true. That means that the RHS of the ||
(the &&
expression) is not evaluated at all because it is not needed to determine the truth of the overall expression.
So, the compiler is correct; you misunderstood precedence in some way.
Why is the first grouping correct? According to first grouping
||
has higher precedence than&&
. What is going wrong with me?
You don't understand precedence, it seems, or you don't understand the interaction of precedence with order of evaluation. The first grouping gives higher precedence to &&
.
If you have a + b * c
, where *
has a higher precedence than +
, then it is evaluated as a + (b * c)
, is it not? Change +
to ||
and *
to &&
and the expressions are isomorphic and the interpretation is similar.
The big difference between the arithmetic expression and the logical expression is that the operands of the logical expression have to be evaluated left-to-right but the operands of the arithmetic expression do not; the compiler could evaluate b * c
before evaluating a
(but must evaluate b * c
before doing the addition). By contrast, in the logical expression (a || b && c
), the compiler must evaluate a
before evaluating b && c
, and when a
turns out to be true, it must not evaluate either b
or c
, let alone b && c
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With