Short circuit and operator precedence in C - c

I know that logical operators in C follow short circuiting but my doubt is that are short circuiting and operator precedence rules not opposing each other. See the below example :
#include<stdio.h>
int main()
{
int a;
int b=5;
a=0 && --b;
printf("%d %d",a,b);
return 0;
}
According to the precedence rules, the highest precedence is of the prefix operator. So --b should be evaluated first and then the && and at last result will be assigned to a. So expected output should be 0 4. But in this case the second operand of && never actually executes and result comes out to be 0 5.
Why precedence rules are not being applied here. Are logical operators exempted from precedence rules? If yes, what other operators show such behavior? And what is the logic behind this behavior?

You're conflating two related but different topics: operator precedence and order of evaluation.
The operator precedence rules dictate how various operators are grouped together. In the case of this expression:
a=0 && --b;
The operators are grouped like this:
a = (0 && (--b));
This has no effect however on which order the operands are evaluated in. The && operator in particular dictates that the left operand is evaluated first, and if it evaluates to 0 the right operand is not evaluated.
So in this case the left side of && which is 0 is evaluated, and because it is 0 the right side which is --b is not evaluated, so b is not incremented.
Here's another example of the difference between operator precedence and order of evaluation.
int val()
{
static x = 2;
x *= 2;
return x;
}
int main()
{
int result = val() + (5 * val());
printf("%d\n", result);
return 0;
}
What will the above program print? As it turns out, there are two possibilities, and both are valid.
In this expression:
val() + (5 * val())
There are no operators that have any type of short circuit behavior. So the compiler is free to evaluate the individual operands of both + and * in any order.
If the first instance of val() is evaluated first, the result will be 4 + ( 5 * 8) == 44. If the second instance of val() is evaluated first, the result will be 8 + (5 * 4) == 28. Again, both are valid since the operands may be evaluated in any order.

Precedence affects how ambiguous expressions are parsed. When there are multiple ways to interpret an expression with several operators, precedence tells us which interpretation is correct. Think of precedence as a mechanism to figure out where the implied parentheses are.
For example in the statement in question there are two valid ways to parse it. If = had higher precedence than && it could be read as:
(a = 0) && --b;
But since && has higher precedence, it's actually interpreted as:
a = (0 && --b);
(Note: Your code's formatting suggests it's the first. Be careful not to mislead!)
Evaluation order is different from precedence. They're related, but independent concepts. After precedence is used to determine the correct parsing of an expression, evaluation order tells us the order to evaluate the operands in. Is it left to right? Right to left? Simultaneous? Unspecified?
For the most part evaluation order is left unspecified. Operators like + and * and << have no defined evaluation order. The compiler is allowed to do whatever it likes, and the programmer must not write code that depends on any particular order. a + b could evaluate a then b, or b then a, or it could even interweave their evaluations.
= and &&, among others, are exceptions. = is always evaluated right to left, and && is left to right with short circuiting.
Here's how evaluation proceeds step-by-step for our statement:
a = (0 && --b), = evaluated right to left
0 && --b, && evaluated left to right with short circuiting
0, evaluates false which triggers short circuiting and cancels the next step
--b, not evaluated due to short circuiting
result is 0
a, variable reference evaluated
a = 0, assignment occurs and overall result is 0
You said that there is no specific order for + and *, but this table shows the order to be left to right. Why so?
The last column of that table is associativity. Associativity breaks precedence ties when we use the same operator twice, or when we use operators with the same precedence.
For example, how should we read a / b / c. Is it:
(a / b) / c, or
a / (b / c)?
According to the table / has left-to-right associativity, so it's the first.
What about chained assignments like foo = bar = baz? Now, assignment has right-to-left associativity, so the correct parsing is foo = (bar = baz).
If this all gets confusing, focus on one simple rule of thumb:
"Precedence and associativity are independent from order of evaluation."

Operator precedence doesn't necessarily tell that an expression gets executed first, it just means that the expression is parsed such that the result of the higher-precedence operation is used in the lower-precedence operation and not the other way around. The actual expressions only get evaluated if they need to!

operator && 's order of evaluation is left to right.
= has lower precedence, in fact only ooperator , has lower precedence than =.
So the expresssion will read a = (0 && --b) being 0 evaluated first given the mentioned order of evaluation.
Since 0 evaluates to false, there is no need to evaluate the second part of the expression because false && true is false, given the first part of the expression is false, the expression will always be false.
If you had || operator the second part of the expression would have to be evaluated.

Operator precedence is not all that plays in the game. There is also order of evaluation. And that mandates that a=0 is evaluated first (evaluation order is from left to right), and then right part after the && is not evaluated at all.
That is how C works.

Related

How this logical operator works? [duplicate]

This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 1 year ago.
#include<stdio.h>
int main()
{
int a=-10,b=3,c=0,d;
d= a++||++b &&c++;
printf("%d %d %d %d ",a,b,c,d);
}
How above expression is evaluates. I have read preceedence but still i am getting confused. Kindly give me the right solution of this in step by step.
In case of || and && operators the order of evaluation is indeed defined as left-to-right.So, operator precedence rules tell you that the grouping should be
(a++) || ((++b) && (c++))
Now, order-of-evaluation rules tell you that first we evaluate a++, then (if necessary) we evaluate ++b, then (if necessary) we evaluate c++, then we evaluate && and finally we evaluate ||.
I have a feeling this is a homework question, so I'll try to give extra explanation. There are actually a lot of concepts going on here!
Here are the main concepts:
Pre- and post- increment and decrement. ++a increments a before the value is used in an expression, while a++ increments a after the value is used in the expression.
Operator precedence. Specifically, && has higher precedence than ||, which means that the assignment of d should be should be read as d = (a++) || (++b && c++);
Expression evaluation order. The link shows a whole list of evaluation rules for C. In particular, item 2 says (paraphrasing) that for operators || and &&, the entire left side is always fully evaluated before any evaluation of the right-hand side begins. This is important because of...
Short-circuit boolean evaluation, which says that, for operators && and ||, if the value of the left-hand term is enough to determine the result of the expression, then the right-hand term is not evaluated at all.
Behaviour of boolean operators in C. There is no inbuilt boolean type in C, and operators && and || work on integer values. In short, an argument is 'true' if it is nonzero, and false if it equals zero. The return value is 1 for true and 0 for false.
Putting this all together, here is what happens:
After the first line, a is -10, b is 3, c is 0 and d is unset.
Next, the variable d needs to be assigned. To determine the value assigned to d, the left hand term of (a++) || (++b && c++) is evaluated, which is a++. The value USED in the expression is 10, however the value of a after this expression is -9 due to the post-increment.
For the purposes of the boolean operator, the value 10 is true, and therefore value of the || expression is 1. Because of short-circuit evaluation, this means that ++b && c++ is not evaluated at all, so the increments do not happen. Thus we have d = 1.
At the end, the values are: a = -9, b = 3, c = 0, d = 1.
So the program prints out -9 3 0 1.

Does && force evaluation of relational, arithmetic operators on left of it before evaluation of higher ranking operators on right (C99)? [duplicate]

This question already has answers here:
What is short-circuit evaluation in C?
(3 answers)
Closed 2 years ago.
Consider the following code:
int y, x; y = 2; x = 0;
x!=0&&y/x>5
My lecturer's textbook on C provides a table for "Precedence hierarchy for the arithmetic, relational, and logical operators" using this table to evaluate the operators in the above expression I get the following precedence:
(1) is /, therefore, do y/x first
(2) is >, (3) is !=, (4) is &&.
If I evaluate the above code using this precedence hierarchy, then the first subexpr to be evaluated is:
y / x
which is
2 / 0, or undefined...
The given answer is 0.
Later on, the textbook also states that, per the ANSI C standard, the operand on the left of && will always be evaluated first, and only if this is 0 will the operand on the right be evaluated.
Does this mean that whenever a logical and (&&) (or a logical or (||) for that matter) appears in an expression along with arithmetic and relational operators, that effectively I need to separate the terms of the overall expression into two groups - terms on the left, and terms on the right, of the &&, and ONLY THEN begin applying the "Precedence hierarchy for the arithmetic, relational, and logical operators" to the operators contained in the overall 'left hand operand'?
This would result in the above expression being evaluated as:
(x!=0) && (y/x>5)
starting with the left operand, (x!=0), which is (0!=0), which is false, so 0, and thus no further evaluation takes place.
--
If this is the case, why does the && operator appear so low down the hierarchy of precedence if its inclusion in an expression dictates what must be done first?
In this case, you're encountering something called "short circuit evaluation". Think of your condition if (x != 0 && y / x > 5) as if (somethingIsTrue && somethingIsTrue). In order for that to be true, it must become if (true && true). In short circuit evaluation, it sees that x !=0 is false and immediately stops evaluating there because no matter what comes after it, the first thing is false so it can never be true.
And yes, to your point, you can sort of think of it as splitting the expressions into groups between the && and || statements. Each of those individual expressions gets evaluated as true or false, and then just look at it as a bunch of true or false statements in between && and || statements. So, for something like if (blah1 && blah2 || blah3), no matter what blah1, blah2, and blah3 are, they will all get evaluated to true or false. And then you just see how it plays out like if (true && true || false) or something like that.
And on a side note, don't bang your head against a wall trying to memorize precedence rules. Most of them are intuitive and you'll get the hang of the correct way of doing things as you program more.
The precedence of operator makes clear how your expression x!=0&&y/x>5 is to be interpreted. Think about it as setting braces. So the compiler would read your expression as (x!=0) && ((y/x)>5). Note here that the operators with the highest precedence are getting braces first, the ones with lower precedence are getting braces later.
Now the evaluation takes place. Evaluation is done from outer to inner. The outmost operator is the one with the lowest priority, the &&. It has two operands, the left one and the right one. Now the standard says that the left one is to be evaluated first. If it is false, then the && returns false (shortcut). If it is true, then the right operand needs to be evaluated.
The good thing about this guaranteed evaluation order is that you can now safely write for example if (x!=0 && y/x>10) or if (pointer!=NULL && pointer->data != 3).
Precedence and associativity only say how to structure an expression. They do not say how to evaluate it. Consider x+y*z. Were it not for precedence, we could structure this expression as (x+y)*z, shown on the left, or x+(y*z), shown on the right.
* +
/ \ / \
+ z x *
/ \ / \
x y y z
Precedence tells us to use the latter. But we can still evaluate x, y, and z in any order. Suppose x, y, and z are actually function calls with side effects; perhaps they print “x”, “y”, and “z”. If we evaluate z and remember its result, then evaluate y, then multiply them, then evaluate x, and then add, we will get the same result as if we evaluate x, then y, then z, then multiply, then add.
Both of these orders of evaluation use the same expression structure, the latter one. So the precedence that gave us the expression structure did not tell us how to evaluate the expression. (Almost—the structure does compel us to get the result of the multiplication before we can use it in the addition.)
The && and || operators have a property beyond precedence: They have a rule that their left operand is evaluated first, and the right operand is evaluated only if the left operand does not determine the result.
Digging deeper, there are two computations associated with some expressions. Each expression has its main effect: to produce a value, such as the sum, product, or logical AND of its operands. Some expressions also have side effects, such as incrementing an object (in x++) or writing output (putchar('c')). The side effect does not have to be done at the same time as the main effect. Generally, it can be done any time during the full expression it is in, and it can be before, during, or after the main effect.
The ordering property of the && and || operators extends to side effects: They require all side effects of their left operand be completed before any part of the right operand is evaluated.

Which would be calculated first?

Only 3 days while learning C. Noticed this in the book:
int main() {
int x = 10, y = 15;
if (x % 2 == y % 3) {
printf("Which one x%2 or y%3 calculated first");
}
}
My question is in if condition. Question is which expression is calculated first, x%3 or y%3?
The short answer is: C does not specify which of x % 2 and y % 3 is computed first, and since there is no side effect in either sub-expression, it does not matter.
The long answer is: Actually, looking at the generated code on Godbolt Compiler Explorer, the expression may be evaluated at compile time and none of these are computed at runtime.
Very few C operators have a specified order of evaluation:
the comma operator ,
the logical and && and logical or || as well as the ternary operator ? : (they actually only evaluate their second or third operand if the first has a specific truth value).
function arguments are evaluated before the function is called, but their relative order of evaluation is unspecified.
I is a tricky question and it was very popular during the interviews some time ago.
If I make it this example a bit less trivial and avoid optimisations:
int comapare(int x, int y) {
int result;
if (result = (x % 2 == y % 3)) {
printf("Which one x%%2 or y%%3 calculated first");
}
return result;
}
The order of evaluation of this particular is undetermined as only logical operators are guaranteed from the left to the right and evaluate the smallest number of operands needed to determine the result of the expression. Operator == along with all other comparison operators is not the logical operator.
Most interviewed candidates answered that it will be evaluated from the left to the right as it is the logical operation.
It's a good question Gaurav. Always have that inquisitive mind as that's how you can attain true learning.
As suggested in the comments, this question relates to Operator Precedence and Associativity.
Here you can get an idea in general.
Here, it's more specific to your question. As you can see there (point# 3), for % operator, it is from Left-to-right.
It is important to distinguish here between how equality == works versus the assignment operator = as the later works from right-to-left. As mentioned in that link, for the assignment operators like =, the expression a=b=c is parsed as a=(b=c), and not as (a=b)=c because of right-to-left associativity.
Hope this will clear your doubts!
Additional clarifications:
Based on subsequent discussions in the comment section, I feel it necessary to remove some of the confusions.
Confusion about operator associativity and order of evaluation:
If two operators are of same precedence, Associativity of operators determines the order in which they execute. The associativity of == is left to right, i.e, the expression on the left is executed first and moves toward the right. So answer to the question of which expression is calculated first in the equation x % 2 == y % 3, the answer would be like this:
1. evaluation of x % 2.
2. evaluation of y % 3.
3. evaluation of ==
Do compilers strictly follow this rule?
Not necessarily. The compilers are free to evaluate such expressions in any order, if they can guarantee a consistent result. 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.
Authentic reference: https://msdn.microsoft.com/en-us/library/2bxt6kc4.aspx

How is this possible if prefix increment operator has right to left associativity?

main()
{
int i=-3, j=2;
int m = ++i || ++j;
printf("%d %d",i,j);
}
if prefix increment operator has right to left associativity then ++j should execute first. But here only ++i executes and ++j doesn't. Why?
Your observation is not related to operator associativity, but to the definition of the execution order of binary logical operators.
You're using ++j as the second operator of a logical operation. In C, binary logical operators have an "early exit", that is, execution stops whenever further execution won't change the result anymore. This is the case when the left operand of || evaluates to TRUE, or the left operand of && evaluates to FALSE. In the former case, the result is TRUE, whatever the other operands yield. In the latter case, it's FALSE, and further evaluation won't change that.
This language feature is very important if you have functions as operands of logical operators. It guarantees that the functions are called in the specified order, and only those functions are evaluated that contribute to the result.
In your example, you evaluate:
int m = ++i || ++j;
Since i == -3, ++i yields -2, which is not 0, hence interpreted as TRUE. So the evaluation of || stops here, and j is not touched.
You are wrong postfix increment operator has left to right associativity.
If you still have doubt do check this link:http://en.cppreference.com/w/cpp/language/operator_precedence
EDIT:
Prefix operators have right to left associativity but precedence and associativity don't tell you about order of evaluation. They only tell you about grouping. For example, precedence is what tells use that ab+c is grouped as (ab)+c instead of a*(b+c). The compiler is free to evaluate a, b and c in any order it sees fit with either of those expressions. Associativity tells you about grouping when you have operators of the same precedence, most often, the same operators. For example, it's what tells you that a-b-c is equivalent to (a-b)-c, not a-(b-c) (otherwise stated, subtraction is left associative).
Order of evaluation is defined by sequence points. There's a sequence point at the end of a full expression (among other things). At the sequence point, all the previous evaluations have to have taken place, and none of the subsequent evaluations can have taken place yet.

&& and || operators [duplicate]

This question already has answers here:
Why does "++x || ++y && ++z" calculate "++x" first, even though operator "&&" has higher precedence than "||"
(11 answers)
Closed 4 years ago.
I came across this code:
int main()
{
int i=1,j=2,k=0,m=0;
m = ++i || ++j && ++k;
printf("%d %d %d %d %d",i,j,k,m);
}
The program returns 2 2 0 1.... Why?
&& has a higher priority than || so ++j && ++k should be evaluated first. Hence I would expect j=3 and k=1. It will return true hence || becomes true so ++i shouldn't be evaluated. But it works other way around.
I would like others to explain to me.
Having higher precedence does not mean it gets evaluated first. It just means it binds tighter. In that example, that expression is equivalent to: ++i || (++j && ++k). What gets evaluated first is ++i because || evaluates left to right. Only if that evaluates to false will ++j && ++k be evaluated because || is short-circuiting.
Actually ++i will be evaluated first. Only if it's false will the right side be evaluated (and in your case it's not).
The fact that "&& has higher priority" relates to precedence (how tightly its operands stick to it) not "whose operands get evaluated first".
Because && is indeed above || in the table, the expression will be interpreted like this:
m = ++i || (++j && ++k)
Short circuit evaluation. If, the left-side of the && is non-zero, only then will the right-hand side be evaluated. Likewise, only if the left-hand side of the || is zero, will the right-hand side be evaluated.
"Higher operator precedence" is not the same as "evaluated first". When you use the short-circuiting operators, they are evaluated left-to-right. The results of any arithmetic will be affected by operator precedence, but that doesn't change the left-t0-right ordering of short circuiting.
The complexity of your example is a good reason for not doing this sort of thing. Even if you figure out the rules and know exactly what it will do, the next programmer to come along and look at the code probably won't.
Basically, || means, "if you have received something which is true, return that, otherwise, return whatever happens afterwards." So, the only thing which is evaluated there is m = (++i != 0). That means "increment i, assign m to the value of i compared to 0, break."
To be more specific, this is what is happening:
i = 1;
i = i + 1;
if( i ) {
m = 1;
}
else { // who cares, this will never happen.
j = j + 1;
if( j ) {
k = k + 1;
m = (k != 0); // 1
}
else {
m = 0;
}
}
In the C language, there are two different issues you need to be aware of: operator precedence and order of evaluation.
Operator precedence determines which operator that gets its operands evaluated first, and also which operands that belong to which operator. For example in the expression a + b * c, the operator * has higher operator precedence than +. Therefore the expression will be evaluated as
a + (b * c)
All operators in the C language have deterministic precedence and they are the same on any compiler.
Order of evaluation determines which operand that gets evaluated first. Note that a sub-expression is also an operand. Order of evaluation is applied after the operator precedence has been determined. If the above a+b*c example has left-to-right order of evaluation, then the operands themselves get evaluated in the order a, b, c. If the operands were for example function calls, then the functions a(), b() and c() would have been executed in that order. All operands in this example need to be evaluated since they are all used. If the compiler can determine that some operands need not be evaluated, it can optimize them away, regardless of whether those operands contain side-effects (such as function calls) or not.
The problem is that order of evaluation of operands is most often unspecified behaviour, meaning that the compiler is free to evaluate either left-to-right or right-to-left, and we cannot know or assume anything about it. This is true for most operands in C, save for a few exceptions where the order of evaluation is always deterministic. Those are the operands of the operators || && ?: ,, where the order of evaluation is guaranteed to be left-to-right. (When using formal C language semantics, one says that there is a sequence point between the evaluation of the left and the right operator.)
So for the specific example m = ++i || ++j && ++k.
The unary prefix ++ operators have the highest precedence, binding the operators i, j and k to them. This syntax is pretty intuitive.
The binary && operator has 2nd highest precedence, binding the operators ++j and ++k to it. So the expression is equivalent to m = ++i || (++j && ++k).
The binary || operator has 3rd highest precedence, binding the operators i++ and (j++ && ++k)= to it.
The assignment operator = has the lowest precedence, binding the operators m and ++i || (++j && ++k) to it.
Further, we can see that both the || and the && operators are among those operators where the order of evaluation is guaranteed to be left to right. In other words, if the left operand of the || operator is evaluated as true, the compiler does not need to evaluate the right operand. In the specific example, ++i is always positive, so the compiler can perform quite an optimization, effectively remaking the expression to m = ++i;
If the value of i wasn't known at compile time, the compiler would have been forced to evaluate the whole expression. Then the expression would have been evaluated in this order:
&& has higher precedence than ||, so start evaluating the && operator.
&& operator is guaranteed to have order of evaluation of operands left-to-right, so perform ++j first.
If the result of ++j is true (larger than zero), and only then, then evaluate the right operator: perform ++k.
Store the result of ++j && ++k in a temporary variable. I'll call it j_and_k here. If both ++j and ++k were positive, then j_and_k will contain value 1 (true), otherwise 0 (false).
|| operator is guaranteed to have order of evaluation of operands left-to-right, so perform ++i first.
If ++i is false (zero), and only then, evaluate the right operator "j_and_k". If one or both of them are positive, the result of the || operator is 1 (true), otherwise it is 0 (false).
m gets assigned the value 1 or 0 depending on the result.
You're seeing logical operator short-circuiting here. If the first part of an || condition is true, then it never evaluates the rest of the expression (because if the first part is a pointer-not-null check you wouldn't want to dereference the pointer in the second part if it's null). Further, since it's in a boolean-result expression the result of ++i is converted back to bool value 1 before being assigned into m.
Avoid this kind of code like the plague, it will only give you debugging nightmares in the short and long term.
Shortcut operators will cause the unnecessary expression components not to be evaluated. Since && has a higher precedence, it would need to be evaluated last if you want to allow the || operator to be able to shortcut the whole expression when ++i evaluates to true. Since this is the case, ++i is the only variable evaluated after the "=".
Precedence and order of evaluation are two different things. Both || and && evaluate their operands left-to-right; precedence doesn't change that.
Given the expression a || b && c, a will be evaluated first. If the result is 0, then b && c will be evaluated.
The order of comparison operators (|| and &&) is more important.
That's why you'd better placed your most important test first.
because || and && short circuit and therefore specify sequence points
Note: this was originally tagged C++ as well, and you get a slightly different answer there as overloaded operators || or && do not short circuit just inbuilt ones

Resources