Confusion with Associativity of Assignment operator in C - c

As we all know that Associativity of assignment operator is from right to left but
in the given code output should be zero if we go from right to left but output is 1 .
main()
{
int a=3,b=2;
a=a==b==0;
printf("%d",a);
}
How output is coming out to be 1 if we go by right to letf??
If we go by right to left then (b==0) should be Evaluated first and gives result 0 and then expression (a==0) is Evaluated also gives 0 and at last a's value will be 0.

Assignment is done RTL, but equality (==) isn't.
The statement is actually:
a = ((a == b) == 0)
The right hand side of the assignment is evaluated from left to right. In steps, this is what's happening:
a == b is 0
0 == 0 is 1
1 is assigned to a

Your code is equivalent to :
a = ((a == b) == 0);

Note, this is phrased this way as it was merged from this question. OP asked why a==b==c is equivalent to a==b && b==c in Objective C (which is a strict superset of C). I asked this answer to be migrated since it cites the specificatio where other answers here do not.
No, it is not, it's like (a==b) == c.
Let's look at a simple counter example to your rule:
(0 == 0 == 0);// evaluates to 0
However
(0 == 0) && (0 == 0) // evaluates to 1
The logic is problematic since:
(0 == 0 == 0) reads out as ((0 == 0) == 0) which is similar to 1 == 0 which is false (0).
For the ambitious student
A little dive on how this is evaluated. Programming languages include grammar which specifies how you read a statement in the language. Siance Objective-C does not have an actual specification I'll use the C specificification since objective-c is a strict superset of c.
The standard states that an equality expression (6.5.9) is evaluated as the following:
Equality Expression:
relational-expression
equality-expression == relational-expression
equality-expression != relational-expression
Our case is the second one, since in a == b == c is read as equality_expression == relational_expression where the first equality expression is a == b.
(Now, the actual result number follow quite a way back to a number literal, equality->relational->shift->additive->multiplicative->cast->unary->postfix->primary->constant , but that's not the point)
So the specification clearly states that a==b==c does not evaluate the same way as a==b && b==c
It's worth mentioning that some languages do support expressions in the form a<b<c however, C is not one such language.

Related

Order of checking the conditions in C

So I was reading about the order of different operators, and I read that && has higher importance than || and it would evaluate sooner (source). Then somebody asked a question about what this piece of code would print:
#include <stdio.h>
int main(){
int a=0, b=0, c=0, d=0;
if(a++>0 || ++b==1 || c--<=0 && d++>c--){
printf("if\na:%d\nb:%d\nc:%d\nd:%d\n",a,b,c,d);
}
else{
printf("else\na:%d\nb:%d\nc:%d\nd:%d\n",a,b,c,d);
}
return 0;
}
And I thought that the c-- <= 0 && d++ > c-- would evaluate first, which is true in total. after the process, c would be equal to -2 and d would be equal to 1. Then it would start checking from the left side, evaluating a++ > 0 || ++b == 1 which is true, a would be 1 at the end and b is 1 in the condition and after that. so the total condition would be true || true and it is true, so we will print:
if
a:1
b:1
c:-2
d:1
Yes? Apparently, no. I've tested it with GCC (Mingw) on my system (Windows 10), and with an online compiler (this one) and both printed:
if
a:1
b:1
c:0
d:0
I've changed the condition into this: if(a++>0 || ++b==1 || (c--<=0 && d++>c--) ) but the output is the exact same thing on both places. Is there something that I don't pay attention to? Or is this something like a bug? It almost looks like that || and && have the same priority and the whole thing is evaluated from the left side, and short-circuits occurs and other things. If I change the ++b==1 part into ++b==0, then the output is the same as I predicted.
Thanks in advance for any kind of help :)
The expression in this question:
if(a++>0 || ++b==1 || c--<=0 && d++>c--)
is a classic example of a horrible, horrible expression, outrageously unrealistic and impractical, and punishingly difficult to understand, which nevertheless does a good job of illustrating a super important point: precedence is not the same as order of evaluation.
What precedence really tells us is how the operators are hooked up with their operands. So given the simplified expression
A || B || C && D
which two subexpressions do the first ||, and the second ||, and the && actually tie together and operate on? If you're a compiler writer, you answer these questions by constructing a "parse tree" which explicitly shows which subexpression(s) go with which operators.
So, given the expression A || B || C && D, does the parse tree for the expression look like this:
&&
/ \
|| D
/ \
|| C
/ \
A B
or like this:
||
/ \
A ||
/ \
B &&
/ \
C D
or like this:
||
/ \
/ \
|| &&
/ \ / \
A B C D
To answer this, we need to know not only that the precedence of && is higher than ||, but also that || is left-associative. Given these facts, the expression
A || B || C && D
is parsed as if it had been written
(A || B) || (C && D)
and, therefore, results in the third of the three candidate parse trees I showed:
||
/ \
/ \
|| &&
/ \ / \
A B C D
But now we're in a position to really see how the "short circuiting" behavior of the || and && operators is going to be applied. That "top" || is going to evaluate its left-hand side and then, if it's false, also evaluate the right-hand side. Similarly, the lower || is going to evaluate its left-hand side. So, no matter what, A is going to get evaluated first. For the expression in the original question, that corresponds to a++ > 0.
Now, a++>0 is false, so we're going to have to evaluate B, which is ++b == 1. Now, that is true, so the result of the first || is "true".
So the result of the second (top) || operator is also "true".
So the right-hand side of the top || operator does not have to be evaluated at all.
So the entire subexpression containing && will not be evaluated at all.
So even though && had the highest precedence, it ended up getting considered last, and (since the stuff to the left involved || and was true) it did not end up getting evaluated at all.
The bottom line, as I started out by saying, is that precedence does not determine order of evaluation.
Also, if it wasn't said elsewhere, this guaranteed, left-to-right behavior is only guaranteed for the || and && operators (and, in a different way, for the ternary ?: operator). If the expression had been
A + B + C * D
it would not have been true that, as I said earlier, "no matter what, A is going to get evaluated first". For arithmetic operators like + and *, there's no way to know whether the left-hand side or the right-hand side is going to get evaluated first.

C multiple assignments to same variable in short-circuited expression

I have three variables: a, b, c. Let's say they are integers. I want to find the first non-zero value among them, in that particular order, without looping. The following seems to work, but I am not sure if that is because I am lucky, or because the language guarantees it:
int main(int argc, char *argv[]) {
int a = 0;
int b = 3;
int c = 5;
int test;
if ((test = a) != 0 || (test = b) != 0 || (test = c) != 0) {
printf("First non-zero: %d\n", test);
} else {
printf("All zero!\n");
}
return 0;
}
Is the repeated assignment with short-circuiting shown here guaranteed to work as intended, or am I missing something?
This might be one place where a three-letter answer would be acceptable, but a two-letter answer might require more explanation.
It would!
Because of the nature of the OR operator if any of the condition is
true then the test stops.
Thus i think what you did was basically equivalent to:
test = a != 0 ? a : b != 0 ? b : c != 0 ? c : 0;
printf("%d\n",test);
but heck yours looks good.
[update]
As per what chqrlie mentioned it can be further simplified to:
test = a ? a : b ? b : c;
Yes, your expression is fully defined because there is a sequence point at each || operator and the short circuit evaluation guarantees that the first non zero value assigned to test completes the expression.
Here is a crazy alternative without sequence points that may produce branchless code:
int test = a + !!a * (b + !!b * c);
printf("%d\n", test);
The code is very bad practice but it is guaranteed to work fine.
This is because the || and && operators have special characteristics - unlike most operators in C, they guarantee that the evaluation of the left operand is sequenced (executed) before the evaluation of the right operand. This is the reason that the code works. There's also a guarantee that the right operand will not be evaluated if it is sufficient to evaluate the left one ("short circuit"). Summarized in 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.
"Sequence point" being the key here, which is what gives the expression a deterministic outcome.
Had you used pretty much any other operator (like for example bitwise |), then the result would be undefined, because you have multiple side effects (assignments) on the same variable test in the same expression.
A more sound version of the same algorithm would involve storing the data in an array and loop through it.

precedence and execution of the operators in the statement

can't understand how the boolean variable "check" is assigned 1 or 0. here 2 == 2 is true but the 2 is not equal to 3 so it should be false.....
/* practicing the precedence of assignment operator */
#include <stdio.h>
int main() {
_Bool check;
check = (2 == 2 != 3);
printf("the value of _Bool is %d\n",check);
return 0;
}
i expect the result to be false
What actually happens is like this
(2 == 2 != 3)
becomes
(2 == 2) != 3)
which is
(1 != 3)
which in turn becomes
(1)
Perhaps what you needed was
(2 == 2 && 2 != 3)
Operator precedence is the same for == and !=, since they both belong to the same group equality operators. To separate operators with same precedence, we use operator associativity of that group, in this case left-to-right. Meaning that 2 == 2 != 3 is guaranteed to be parsed as (2 == 2) != 3. So we get:
2 == 2 -> 1
1 != 3 -> 1
Notably both == and != have higher precedence than =, so the parenthesis in your expression = (2 == 2 != 3) isn't needed (but good practice to use if you are uncertain about precedence).
Regarding order of execution/evaluation, that's another term not to confuse with operator precedence. The order of evaluation of the == and != operands in your expression is unspecified, meaning we can't know which one that will get executed first.
In this case it doesn't matter, but if we had this check = a() == b() != c();, it could have. Here, we can't know which of the 3 functions that are executed first. We only know that operator precedence says that the result of a should be compared with the result of b before the result of c, but the function c may still be executed first.
Two things:
The equality operators have same precedence and left to right associativity, so (2 ==2 != 3) is the same as ((2 == 2) != 3) which is (1 != 3) which is true.
The equality operations return an int value as result, so using a _Bool (or, bool with stdbool.h) is not necessary.

C operator precedence, logical vs unary in a++ && b++ || ++c

In the follwing code,
int a = 1, b = 2, c = 3, d;
d = a++ && b++ || c++;
printf("%d\n", c);
The output will be 3 and I get that or evaluates first condition, sees it as 1 and then doesn't care about the other condition but in c, unary operators have a higher precedence than logical operators and like in maths
2 * 3 + 3 * 4
we would evaluate the above expression by first evaluating product and then the summation, why doesn't c do the same? First evaluate all the unary operators, and then the logical thing?
Please realize that precedence is not the same concept as order of evaluation. The special behavior of && and || says that the right-hand side is not evaluated at all if it doesn't have to be. Precedence tells you something about how it would be evaluated if it were evaluated.
Stated another way, precedence helps describe how to parse an expression. But it does not directly say how to evaluate it. Precedence tells us that the way to parse the expression you asked about is:
||
/ \
/ \
&& c++
/ \
/ \
a++ b++
But then when we go to evaluate this parse tree, the short-circuiting behavior of && and || tells us that if the left-hand side determines the outcome, we don't go down the right-hand side and evaluate anything at all. In this case, since a++ && b++ is true, the || operator knows that its result is going to be 1, so it doesn't cause the c++ part to be evaluated at all.
That's also why conditional expressions like
if(p != NULL && *p != '\0')
and
if(n == 0 || sum / n == 0)
are safe. The first one will not crash, will not attempt to access *p, in the case where p is NULL. The second one will not divide by 0 if n is 0.
It's very easy to get the wrong impression abut precedence and order of evaluation. When we have an expression like
1 + 2 * 3
we always say things like "the higher precedence of * over + means that the multiplication happens first". But what if we throw in some function calls, like this:
f() + g() * h()
Which of those three functions is going to get called first? It turns out we have no idea. Precedence doesn't tell us that. The compiler could arrange to call f() first, even though its result is needed last. See also this answer.

Can't understand this if statement

I've a C university exam coming up next week and i was looking at old exam papers a one of the questions gives this fragmented bit of code.
int a=2, b=-1, c=0;
if (a-2||b&&c||a){
printf("True\n");
} else {
printf("False\n");
}
We have to determine what the output of this code will be but the if statement makes no sense to me any if statement I've come across has been very specific like saying
if( x == 0)
I don't know what this is looking for my only assumption is that its going to be always true. Am I right or is there more to it then that?
This assignment has two goals:
to show what booleans are in C: Essentially they evaluate to ints with false mapping to 0 and true mapping to 1. In turn, any numeric or pointer value can be used in an integer context, with the respective zero value (0, 0.0, NULL (pointer), 0.0f, 0L etc.) evaluating as false and all others as true.
to show the precedence of operators
&& has a higher precedence than ||, so this statement is equivalent to
a-2 || (b&&c) || a
which will evaluate to true if any of the values is true.
As a==2, a-2 is 0. c is 0, so b && c is 0 as well.
So we have 0 || 0 || a, which is true as a is 2.
Most languages interprets non-zero integers as true and zero as false, so here you would have to calculate each one of the terms. Without any parenthesis, I would suggest that the && statement is taken in account first. So we have:
if (2-2 // gives zero
|| // OR
-1 && 0 // -1 AND 0 gives false
|| // OR
a) // Which is 2, which is true
So you're right, this statement is always true. This exercice was about showing predecence orders, and the fact that everything is numerical, even in boolean logic.
This is really important for you to understand.
If the predecence was the other way around (|| > &&), you must understand that it would have been false instead. I think this example's whole point is here.
(a-2 || b) && (c || a)
false && true
--> false
You need to understand that truth and falsity in C is always numerical.
https://www.le.ac.uk/users/rjm1/cotter/page_37.htm
Namely, anything that evaluates to numerical zero is false, and anything that evaluates to numerical non-zero is true.
In c language integers 0 is treated as false and any non-zero integer value is true but it should be noted that it is language specific and the sme statement will show compilation error in java as java is more strict and integers are not converted to booleans.
Talking about the above assignment problem the expression inside if statement will evaluate to true as
(a-2||b&&c||a) is same as
(2-2||-1&&0||2) which is same as
(0||0||2) which is evaluated as
(false||false||true) and hence the entire expression evaluates to
true.
hope it helps.
int a=2, b=-1, c=0;
int first=a-2; //0 -> false
bool second= b&& c; // nonZero&&zero -> true&&false -> false
int third = 2; // nonZero -> true
// false|| false|| true -> true
if (first || second || third ){
printf("True\n");
} else {
printf("False\n");
}
you need to understand two things before solving this problem that is
operator precedence and
associativity of operators
operator precedence tells c compiler that which operation to perform first.
and if two operators have same precedence than associativity tells evaluate left to right or right to left in you expression
int a=2, b=-1, c=0;
if (a-2||b&&c||a){
you can think it as
if((a-2)||(b&&c)||a){}
means - has top precedence so it will solved first
reduced to if(0||(b&&c)||a){}
then && has higher precedence so
reduced to if(0||false||a)
then the associativity is left to right so
reduced to if(false||a)
that is(false||2)
return true
In almost every programming language as far as I know 0 means false and 1 means true.
So coming up to your question: you have used && and || operators. Both of these are called Logical operators.
Now first block of yours is a-2||b :-
2-2||-1 so 0||-1. Now since the right expression of || is -1 the or operator will return 1 i.e. True because one of the values of 0 and -1 is non-zero 0 i.e. -1.
Therefore the expression resolves to 1&&c||a :-
Now c=0, therefore 1&&0 returns a 0 because && will only return 1 if both the expressions right and left of it are non zero.
So expression becomes 0||2 :-
Now since || (or operator) requires only one of operands either on right or left side to be non zero hence 0||2 returns 1.
Now your if (a-2||b&&c||a) statement resolves to
if (1)
{
printf("True\n"); }
else......
Therefore since 1 means TRUE the if statement will execute and you will get output as True.

Resources