Is the order of the boolean expressions in if statement fixed? - c

Is the order of boolean expressions in this if statement fixed?
if(boolean_expression_1 || boolean_expression_2) {
}
Is boolean_expression_1 always evaluated before boolean_expression_2? Is the order of evaluation a standard in C?

Yes. It's guaranteed. It's called "short circuit" evaluation.
From C11 draft, 6.5.14 Logical OR operator:
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.
(emphasis mine).

Related

() has the highest priority, why is it short-circuited?

() has the highest priority, why is it short-circuited?
int a = 1, b = 0;
(--a)&&(b++);
Why is (b++) still short-circuited?
I don't find the term "short-circuit" particularly helpful.
It is better to say that && and || have left-to-right order of evaluation. The C standard (6.5.13) actually explains this well:
the && operator guarantees left-to-right evaluation ...
If the first operand compares equal to 0, the second
operand is not evaluated.
And that's it. The left operand --a evaluates to 0.
What is the difference between operator precedence and order of evaluation?
In this case, all that matters is order of evaluation. Operator precedence only guarantees that the expression is parsed as expected - which operands that "glue" to which operator.
The expression (--a) uses the prefix operator and evaluates to 0. This is false and the 2nd expression is not evaluated due to short-circuit as you noted.
To understand consider the following expression
a * b + c * d
If to assume that the operands of the operator + are evaluated from left to right then at first the expression a * b will be evaluated and then the expression c * d.
The assumption relative to the order of evaluations of operands of the operator + is not valid. But it is valid for the operator &&.
So left operand of the expression
(--a)&&(b++);
is evaluated first. And if its value is not equal to 0 then the second operand is evaluated.
From the C Standard (6.5.13 Logical AND operator)
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.
You are right that you can override operator precedence using parenthesis ().
For example, the expression
a && b || c
is equivalent to
(a && b) || c,
because && has a higher precedence than ||. You can override this precedence by changing it to
a && (b || c)
so that now the || has precedence over &&.
However, operator procedence doesn't change the behavior of the individual operators. In particular, both operators will still use short-circuiting. So, even if || has higher precedence than &&, the && operator will still evaluate its left-hand operand before its right-hand operand.
In both of my examples above, the && operator will still evalulate a before evaluating b or (b || c). Operator precedence will only affect whether the right-hand operand of the && operator is the expression b or (b || c).
Therefore, in your example, by writing (--a)&&(b++) instead of --a&&b++, you are merely ensuring that the -- and ++ operators have precedence over the && operator. This is not necessary, because he C language specifies that these operators already have precedence.
In the hypothetical scenario that the C language had instead specified that the && operator had precedence over the -- and ++ operators, then the expression --a&&b++ would be interpreted as --(a&&b)++, and it would be necessary to write (--a)&&(b++) to prevent this interpretation. But this is not the case.

C Operators and Precedence

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.

"And" and "Or" operators in conditionals in C [duplicate]

This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 6 years ago.
I always wondered about something and couldn`t find an answer somewhere else. If I have this piece of code:
if ((cond1) &&(cond2) && (cond 3) && (cond 4))
{
// do something
}
Let`s say the first condition is false, then my program will verify the other conditions too, or just skip verifying them?
But if I have
if ((cond1) ||(cond2) || (cond 3) || (cond 4))
{
// do something
}
and cond 1 is true, will my program go instantly on the if part or continue to verify the other conditions too?
Quoting C11 standard, chapter §6.5.13, Logical AND operator (emphasis mine)
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.
So, if the first condition (LHS operand) evaluates to false, the later conditions, i.e., RHS operand of the && is not evaluated.
Similarly (Ironically, rather), for Logical "OR" operator,
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 C both && and || "sort-circuit", meaning if evaluation of the left operand is enough to determine the outcome then the right operand is not evaluated.

order of evaluation of comparison operator?

I have learnt that logical operator are guaranteed that their evaluation are from left-to right but I was wondering what are the order of evaluation of comparison operator. For instance expression1 < expression2 in other words is it guaranteed that expression1 will be first evaluated before expression2.
According to the standard:
J.1 Unspecified behavior
The following are unspecified:....
— The order in which subexpressions are evaluated and the order in which side effects
take place, except as specified for the function-call (), &&, ||, ?:, and comma
operators (6.5).
Generally speaking, the order of evaluation of subexpressions within an expression is undefined.
The only place where there is an order, i.e. sequence points, is the || (logical OR), && (logical AND), , (comma), and ?: (ternary) operators.
In the case of &&, if the expression on the left evaluates to false (i.e. 0), the result is known to be false and the right side is not evaluated. Similarly for || if the expression on the left evaluates to true (i.e. not 0), the result is known to be true and the right side is not evaluated.
For the ternary operator, the conditional is evaluated first. If it evaluates to true then only the middle part is evaluated, otherwise only the third part is evaluated.
For the comma operator, the left side is evaluated first, then the right side.
From the C standard:
6.5.13.4 Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation; there is a sequence point
after the evaluation of the first operand. If the first
operand compares equal to 0, the second operand is not evaluated.
...
6.5.14.4 Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; there is a sequence point after the
evaluation of the first operand. If the first operand
compares unequal to 0, the second operand is not evaluated.
...
6.5.15.4 The first operand is evaluated; there is a sequence point after its evaluation. The second operand is evaluated only if the
first compares unequal to 0; the third operand is evaluated only if
the first compares equal to 0; the result is the value of the second
or third operand (whichever is evaluated), converted to the type
described below. If an attempt is made to modify the result of a
conditional operator or to access it after the next sequence point,
the behavior is undefined.
....
6.5.17.2 The left operand of a comma operator is evaluated as a void expression; there is a sequence point after its
evaluation. Then the right operand is evaluated; the result has its
type and value. If an attempt is made to modify the result of a comma
operator or to access it after the next sequence point, the behavior
is undefined.
No, the spec does not mention the order of evaluation for the operand of relational operators. It's unspecified.
Just to add, relational operators are left-to-right associative.

Short circuit evaluation of a statement with ++ operator in C

I have executed the following code in Code::Blocks 10.05 on Windows 7.
int a=0,b=0,c;
c=a++&&b++;
printf("\na=%d\nb=%d\nc=%d\n\n",a,b,c);
The output I obtained is given below,
a=1
b=0
c=0
This makes perfect sense because of short circuit evaluation.
The expression a++ is post increment and 0 is returned to the logical and (&&). Hence the part b++ is not evaluated since both 0 && 0 and
0 && 1 evaluates to 0.
But here arises my doubt. The precedence value of operators clearly states that ++ is having higher precedence over &&. So my understanding was like this, both a++ and b++ are evaluated and then && only checks the result of expression a++ to come to a decision. But this has not happened only a++ is evaluated here.
What is the reason for this behavior? Does && being a sequence point has something to do with this behavior? If so why we say that && is having lower precedence than ++?
You are confused about precedence and order of evaluation.
Precedence defines how the operators are grouped, i.e
c = a++ && b++;
is equivalent to:
c = ((a++) && (b++));
Order of evaluation defines how the expression is evaluated, the short circuit of && means a++ is evaluated first, if it's zero, the end; if it's not zero, b++ is then evaluated.
As another example:
c = (a++) + (b++);
Is a++ evaluated before b++? The answer is we don't know. Most operators don't define the order of evaluation. && is one of the few operators that do define. (The rest are ||, , and ?:)
There are two concepts here - order of precedence and order of evaluation. Order of precedence will have an impact only if an expression (or sub-expression) is evaluated.
In general, the order of evaluation is not sequenced. Given an operator, its operands can be evaluated in any order. The arguments of a function can be evaluated in any order.
From the C++ Standard:
1.9 Program execution
15 Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.
and
8.3.6 Default arguments
9 Default arguments are evaluated each time the function is called. The order of evaluation of function arguments is unspecified.
For the logical AND operator, &&, the C++11 standard says:
5.14 Logical AND operator
1 The && operator groups left-to-right. The operands are both contextually converted to type bool (Clause 4). The result is true if both operands are true and false otherwise. Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.
Similar exception is specified for the logical OR operator, ||.
Since b++ is not evaluated due to short circuiting of the expression because of && operator, the order of precedence of the operators has no significance in this particular case.

Resources