#include <stdio.h>
int main(void) {
int d, a = 1 & 0 && (d=4);
printf("%d\n", d);
return 0;
}
According to the operator precedence () statement d should be assigned but in the above program logical and is executed first. d value is not assigned to 4. Please anyone help me to understand the above program. I have tried with gcc and some online compilers
Let's look at f() + g() * h() first.
Precedence and associativity defines what is an operand of what. For example, C operator precedence and associativity tells us that
f() + g() * h()
means
f() + ( g() * h() ) # * has higher precedence than +
rather than
( f() + g() ) * h() # If + had higher precedence than *
Notably, precedence doesn't determine the order in which operands are evaluated. In our example, the three functions could be called in any order, as long as the result of g() and the result of h() are multiplied together, and that the result of the multiplication is added to the result of f().
Back to
1 & 0 && ( d = 4 )
Precedence and associativity simply tell us that the above is equivalent to the following:
( 1 & 0 ) && ( d = 4 ) # & has higher precedence than &&
So what does this do?
&& dictates that its right-hand side is only evaluated if its left-hand side is true. This is called short-circuit evaluation or short-circuiting.
1 & 0 is false, so d = 4 is never evaluated. This leaves d unchanged, and thus uninitialized.
1 & 0 && (d=4) is evaluated like this: (1 & 0) && (d=4)
(1 & 0) is 0
because of short circuiting the right hand side of the && operator is not evaluated
therefore d=4 is never evaluated
therefore d is never assigned
and therefore d contains garbage because local variables are not initialized
If you change int d to int d = 42, the output of your program will be 42
Related
#define MAX(a,b) ((a)>(b) ? (a) : (b))
int main(void) {
int a=2;
int b=3;
int c = MAX(a++,b++); // c=((a++)>(b++) ? (a++) : (b++));
printf("\na= %d", a);// a=3
printf("\nb= %d", b);//b=5
printf("\nc= %d", c);//c=4
a=3;
b=2;
cc = MAX(a++,b++); // c=((a++)>(b++) ? (a++) : (b++));
printf("\na= %d", a); // a=5
printf("\nb= %d", b); //b=3
printf("\nc= %d", c); //c=4
return 0;
}
I would like to know why c is not evaluating to 5.
It appears to me the evaluation order should be:
First both a and be get incremented in (a++)>(b++)
If for example the first one is greater, the ternary operator in
c=((a++)>(b++) ? (a++) : (b++)), goes to (a++), so a
increments again.
The result of the ternary expression, which is a twice-increment,
should be assigned to c, then c should have the greater value
twice-incremented, that is 5. However, I am getting 4. I suspect the
greater value's second increment is happening at the end, but I can't
explain why, since the parentheses seem to indicate that the
assignment comes at the end.
Any idea?
The postfix ++ operator has a result and a side effect. The result of a++ is the value of a before the increment - given
int a = 1;
int x = a++;
the value of x will be 1 and the value of a will be 2. Note that the side effect of adding 1 to a does not have to be applied immediately after evaluation - it only has to be applied before the next sequence point.
So, looking at
((a++) > (b++)) ? (a++) : (b++)
The ?: operator forces left-to-right evaluation, so the first thing that happens is that (a++) > (b++) is evaluated1. Since a is initially 2 and b is initially 3, the result of the expression is false (0). The ? operator introduces a sequence point, so the side effects to a and b are applied and a is now 3 and b is now 4.
Since the result of the condition expression was 0, we evaluate b++. Same thing, the result of the expression is the current value of b (4), and that value gets assigned to c. The side effect to b is applied at some point, and by the time everything's finished, a is 3, b is 5, and c is 4.
Although within that expression either a++ or b++ may be evaluated first, since the > operator doesn't force left-to-right evaluation.
Let's consider for example this declaration
int c = MAX(a++,b++);
after the macro substitution there will be
int c = (( a++) >( b++ ) ? (a++) : (b++));
The variables a and b are initialized like
int a=2;
int b=3;
As a is less than b then the third expression (b++) will be evaluated as a result of the conditional operator. In the first expression ( a++) >( b++ ) a and b were incremented. There is a sequence point after the evaluation of the first expression.
So a will be set to 3, b will be set to 4.
As it was already said the value of the conditional operator is the value of the third expression (b++) where there is used the post-increment. The value of the post-increment operator is the value of its operand before incrementing.
From the C Standard (6.5.2.4 Postfix increment and decrement operators)
2 The result of the postfix ++ operator is the value of the
operand. As a side effect, the value of the operand object is
incremented (that is, the value 1 of the appropriate type is added to
it).
So the value of the conditional operator is 4. This value will be assigned to the variable c. But as a side effect the value of b will be incremented.
Thus after this declaration a will be equal to 3, b will be equal to 5 and c will be equal to 4.
For clarity this declaration
int c = (( a++) >( b++ ) ? (a++) : (b++));
in fact can be rewritten in the logically equivalent way.
int result = a > b;
++a;
++b;
int c;
if ( result != 0 )
{
c = a++;
}
else
{
c = b++;
}
For a++ it's equivalent as saying
int temp = a;
a = a + 1;
return temp;
so in the case of a=2, b=3, we can go to the condition (a++)>(b++) and we can have a rewritten as
int temp1 = a;
a = a + 1;
return temp1;
and b rewritten as
int temp2 = b;
b = b + 1;
return temp2;
now since it's only a conditional statement, we're really just evaluating the old values of a and b before the increment which is temp1 = 2 and temp2 = 3 while at the same time a and b values have changed a = 3, b = 4. Since temp1 < temp2 from the old value, we go to the false clause of the ternary operator (b++) and do the same thing as we did before
int temp3 = b;
b = b + 1;
return temp3;
so now b is 5 while the returned temp3 is the previous value of b which is 4. Hope this helps!
#include <stdio.h>
int main() {
int a = 1;
int b = a || (a | a) && a++;
printf("%d %d\n", a, b);
return 0;
}
when I ran this code the results were 1 and 1.
According to the C language Operator Precedence the operation && is supposed to happen before the operation ||. So shouldn't the result be 2 1 ? (a = 2, b = 1)
when OR'ing expressions in C, a shortcut is taken, I.E. as soon as an expression is evaluated to TRUE, the rest of the OR'd expressions are not evaluated
The first expression a evaluates to TRUE, so all the rest of the expressions are not evaluated, so a is never incremented
When applying the operator precedence rules, the expression is equivalent to:
int b = a || ((a | a) && a++);
The evaluation or the operands to || and && is performed from left to right and shortcut evaluation prevents evaluating the right operand if the left operand can determine the result: since a is non zero, a || anything evaluates to 1 without evaluating the right operand, hence bypassing the a++ side effect.
Therefore both a and b have value 1 and the program prints 1 1.
Conversely, if you had written int b = (a || ((a | a)) && a++;, the left operand of && would have value 1, so the right operand need to be evaluated. a++ evaluates to 1 but increments a, so b have final value 1 and a is set to 2, producing your expected result.
The confusion comes from equating operator precedence with order of evaluation. These are two separate notions: operator precedence determines the order in which to apply the operators, but does not determine the order of evaluation of their operands.
Only four operators have a specified order of evaluation of their operands: &&, ||, ? : and , and the first 2 may skip evaluation of one, depending on the value of the other operand and the third only evaluates the first and only one among the second and third operands. For other operators, the order of evaluation of the operands is unspecified, and it may differ from one compiler to another, one expression to another or even one run to another, although unlikely.
When I try to put a || (a | a) into a parenthesis. The result was as you expected.
So I guess that when C compiler executes an OR operator and it get a True value to the OR, the execution will finish immediately.
In your case, when the compiler executed the a || (a | a) (1 || something) operation. Value of b will be declared to 1 right away and a++ operator won't be execute.
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.
This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 5 years ago.
I am curious about the exact definition of the C standard about variable assignment within a conditional clause. Here is a small example:
int foo() {
...
}
int bar() {
...
}
int main () {
int a, b, x, y;
...
if ( (a = foo()) == x && (b = bar() == y ) {
...
}
...
}
A test with GCC revealed that if (a = foo()) != x, b = bar() will not be executed. On the one hand this behavior is optimal, as it will not waste any time with the calculation of bar(). On the other hand, though, the value of b is somewhat undefined, because it depends on the result of foo(), which actually has nothing to do with b.
I wonder if there is an explicit definition for such cases in the C standard and what the reasons for that definition would be. And finally, what is considered to be best practice for writing such code?
A test with GCC revealed that if (a = foo()) != x, b = bar() will not be executed.
Well, that's the property of the logical AND (&&) operator.
Quoting C11, chapter ยง6.5.13, 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.
That said, for the assignment of b, you're right, if the first operand is FALSE, the value of b remains indeterminate and any usage of the variable may lead to undefined behavior.
(One of the) The best practice, is to initialize local variables upon definition to avoid use of indeterminate value.
The operator && consists of short circuit evaluation: the second subexpression is only evaluated if its result is needed in order to determine the result of the whole expression.
In your example, in the expression:
(a = foo()) == x && (b = bar() == y)
if the first subexpression (a = foo()) == x is evaluated to false, the result of the expression above is also false regardless of the result that the subexpression (b = bar() == y) would produce.
Because of both short-circuit evaluation and the fact that (a = foo()) == x evaluates to false, the expression (b = bar() == y) is never evaluated.
It's very simple: the second (i.e. right hand) argument of && will not be evaluated if the first argument evaluates to 0.
So, (b = bar() == y ) will not be evaluated if (a = foo()) == x is 0.
The fact that this could leave b uninitialised - with potentially undefined results - is a touchstone for the fact that you ought not code this way.
You could use
if ((a = foo() == x) & (b = bar() == y))
if you want both sides to always be evaluated: & is not short-circuited. But beware of unexpected effects if the arguments can evaluate to something other than 0 or 1 (which they don't in this case).
It is known that both assignment = and conditional ?: operators have right associativity. In following code sample:
#include <stdio.h>
int main(void)
{
int a, b, c, d;
a = b = c = d = 1;
1 ? a++ : b ? c++ : d;
printf("%d %d %d %d\n", a, b, c, d);
return 0;
}
the assignment:
a = b = c = d = 1;
is equivalent to:
a = (b = (c = (d = 1)));
and correspondingly:
1 ? a++ : b ? c++ : d;
is the same as:
1 ? a++ : (b ? c++ : d);
What the Standard say about this last case? Does it guarantee that such combined expression is evaluated from left to right (so the c++ part is not evaluated), just as opposite to assignment?
The evaluation order of ?: is guaranteed: the first operand is evaluated first, then evaluate the second or the third operand depending on whether the first operand is true.
You are mainly confused about the relationship between operator precedence/associativity and order of evaluation. They play different roles. The former decides how operators are grouped, while the latter decides which sub-expression is evaluated first.
Consider the expression a * b + c * d, the precedence rule means it's equivalent to (a * b) + (c * d). But is it guaranteed that the compiler will evaluate a * b before c * d? The answer is no, in this example, the operator + doesn't guarantee the order of evaluation.
The conditional operator ?: is one of the few operators that do have a specified order of evaluation. (The rest are &&, ||, and ,).
In your example
1 ? a++ : b ? c++ : d;
1 ? a++ : (b ? c++ : d);
are always equivalent, in both expressions, 1 is evaluated first, and since it's true, a++ is evaluated next, the end.
Associativity and precedence do not define order of evaluation. These concepts are completely unrelated. Order of evaluation in C is defined by sequencing rules, not by precedence or associativity.
It is true that a = b = c = d = 1; is associated as a = (b = (c = (d = 1)));, but that does not mean that d = 1 should be evaluated first, especially in C language, where assignment operator evaluates to an rvalue.
Associtivity simply says that c should receive value 1 converted to the type of d ("as if" it was read from d). But that does not mean that d = 1 should be done first. In your example all variables have the same type, which means that the whole thing is equivalent to a = 1; b = 1; c = 1; d = 1; in absolutely any order. There's no sequencing inside a = b = c = d = 1 expression.
The same logic applies to ?: operator. Its associativity simply tells you which operand belongs to which operator. And the grouping is indeed 1 ? a++ : (b ? c++ : d);. But associativity does not tell you anything about the order of evaluation. Order of evaluation in ?: operator is defined separately and independently: the condition is always evaluated (sequenced) first, then one (and only one) of the branches is evaluated. In your example 1 is evaluated first, then a++ is evaluated and its result becomes the result of the entire expression. The (b ? c++ : d) part is not even touched.
1 ? a++ : b ? c++ : d;
is equivalent to
if (1) {
a++;
}
else {
if (b) {
c++;
}
else {
d;
}
}
So, the output will be
2 1 1 1