This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 2 years ago.
#include <stdio.h>
int main()
{
int a = 1;
int b = 1;
int c = a || --b;
int d = a-- && --b;
printf("a=%d, b= %d, c= %d, d= %d",a,b,c,d);
return 0;
}
In th above code, I expected output to be a=0, b= -1, c= 1, d= 0 but the output was a=0, b= 0, c= 1, d= 0
Screenshot_VS Code
In the expression used as an initializer in this declaration
int c = a || --b;
as the operand a is not equal to 0 then the expression --b is not evaluated.
So the variable c is initialized by 1.
From the C Standard (6.5.14 Logical OR operator)
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.
In the expression used as an initializer in tjis declaration
int d = a-- && --b;
the operand a-- is not equal to 0 (the value of the postfix operator is the value of its operand before decrementing). So the operand --b is evaluated.
As its value is equal to 0 then the variable d is initialized by 0.
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.
As a result a and b will be equal 0 after this declaration.
Related
The expression b = 5 << sizeof(a++); is an undefined behavior. But is c = a && b << --a; or c = a || b << a++; also an undefined behavior? I think it is undefined behavior, but I am not sure.
He said "we should not have any side effects within the operands of an sizeof operator" [From a comment, apparently the reason b = 5 << sizeof(a++); was said to have undefined behavior.]
If the teacher said this because such side effects might give rise to undefined behavior, they are wrong. The operand of sizeof is not evaluated unless it is a variable length array type (C 2018 6.5.3.4 2), so no side effects occur for sizeof(a++). Further, even if the expression were evaluated, there is no rule that mere presence of side effects in a sizeof operand causes undefined behavior.
None of the displayed statements have undefined behavior per se. (Some definitions and values for a, b, and c might give rise to undefined behavior.)
In c = a && b << --a;, the left operand of &&, a, is specified to be evaluated before the right operand, b << --a, and there is a sequence point between them (C 2018 6.5.13 4), so the fact that --a modifies a and a is also used in the left operand does not trigger the rule (C 2018 6.5 2) that behavior is undefined if a side effect on a scalar object is unsequenced relative to a use of its value.
Similarly, in c = a || b << a++;, there is a sequence point between evaluation of the left operand a and the right operand b << a++ (C 2018 6.5.14 4).
This statement
b = 5 << sizeof(a++);
is a valid expression statement. There is no undefined behavior. Pay attention to that the expression used in the operator sizeof is not evaluated.
The undefined behavior can occur in this statement in one case (the C Standard. 6.5.7 Bitwise shift operators)
If the value of the right operand is negative or is greater than or
equal to the width of the promoted left operand, the behavior is
undefined.
But the type size_t of an expression with the sizeof operator is an unsigned integer type a value of which can not be negative.
In the other two statements
c = a && b << --a;
and
c = a || b << a++;
that are equivalent to
c = ( a ) && ( b << --a );
and
c = ( a ) || ( b << a++ );
neither one has undefined behavior because there is a sequence point after the evaluation of the first operand of the logical operators AND and OR.
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.
and (6.5.14 Logical OR operator)
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.
The undefined behavior can occur only in the sub-expressions with the shift operator provided that these operands will be evaluated when values of the expressions --a or a++ are negative or too big. See the quote from the C Standard in the beginning of the answer.
Here is a correct demonstration program
#include <stdio.h>
int main( void )
{
int a = 1;
int b = 10;
int c = a && b << --a;
printf ( "a = %d, b = %d, c = %d\n", a, b, c );
c = a || b << a++;
printf ( "a = %d, b = %d, c = %d\n", a, b, c );
}
The program output is
a = 0, b = 10, c = 1
a = 1, b = 10, c = 1
In the both expressions
b << --a
and
b << a++
the value of the right operand of the shift-left operator is equal to 0. So the value of the expressions is equal to 10 because no shifting was done.
I'm studying C from A Book on C by Kelley-Pohl, and there's this exercise that I don't understand:
int a = 0, b = 0, x;
x = 0 && (a = b = 777);
printf("%d %d %d\n", a, b, x);
x = 777 || (a = ++b);
printf("%d %d %d\n", a, b, x);
They just say to imagine the output and compare it to the real one. I thought the output would have been
777 777 0
778 778 1
but it is
0 0 0
0 0 1
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.
In this expression statement
x = 0 && (a = b = 777);
the first operand compares equal to 0. So the second operand is not evaluated that is the values of the variables a and b are not changed. So the variable x will be set to 0 according to the paragraph #3 of the section.
From the C Standard (6.5.14 Logical OR operator)
3 The || operator shall yield 1 if either of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
and
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.
In this expression statement
x = 777 || (a = ++b);
the first operand compares unequal to 0. So the second operand is not evaluated that is the values of the variables a and b are not changed.. So the variable x will be set to 1 according to the paragraph #3 of the section.
If you will change the order of the operands in the expressions like
x = (a = b = 777) && 0;
x = (a = ++b) || 777;
you get the expected by you result.
The && operator uses lazy evaluation. If either side of the && operator is false, then the whole expression is false.
C checks the truth value of the left hand side of the operator, which in your case is 0. Since 0 is false in c, then the right hand side expression of the operation, (a = b = 777), is never evaluated.
The second case is similar, except that || returns true if the left hand side expression returns true. Also remember that in c, anything that is not 0 is considered true.
Hope this helps.
Another trap in this expression is that; the precendence of the operators. Such as &&, || (logical and, logical or) operators have higher precedence to the assignment operator(=).
in this case x=(0&&(a=b=777)) is same as x=0&&(a=b=777), however x=(0&(a=b=777)) is more readable than the previous one.
Logical operators select one of their operands and returns the result accordingly.
They also force their operands to be boolean as true or false.
In this expression "x=0&&(a=b=777)" since the first operand is false the result will be equal to first operand.Second operand is short circuited and will not be executed.So the output will be a=b=0, x=0.
x=777 || (a=++b) in this expression since the first operand is true the result will be equal to the first operand and logical operator will not check the second operand, logical OR operator will bypass the second operand.In this expression since the first operand is true (777 is converted to true) the result will be True means x=1.Since the second operand is skipped "a" and "b" values will remain same as their previous values, in this case 0,0
I'm studying C from A Book on C by Kelley-Pohl, and there's this exercise that I don't understand:
int a = 0, b = 0, x;
x = 0 && (a = b = 777);
printf("%d %d %d\n", a, b, x);
x = 777 || (a = ++b);
printf("%d %d %d\n", a, b, x);
They just say to imagine the output and compare it to the real one. I thought the output would have been
777 777 0
778 778 1
but it is
0 0 0
0 0 1
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.
In this expression statement
x = 0 && (a = b = 777);
the first operand compares equal to 0. So the second operand is not evaluated that is the values of the variables a and b are not changed. So the variable x will be set to 0 according to the paragraph #3 of the section.
From the C Standard (6.5.14 Logical OR operator)
3 The || operator shall yield 1 if either of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
and
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.
In this expression statement
x = 777 || (a = ++b);
the first operand compares unequal to 0. So the second operand is not evaluated that is the values of the variables a and b are not changed.. So the variable x will be set to 1 according to the paragraph #3 of the section.
If you will change the order of the operands in the expressions like
x = (a = b = 777) && 0;
x = (a = ++b) || 777;
you get the expected by you result.
The && operator uses lazy evaluation. If either side of the && operator is false, then the whole expression is false.
C checks the truth value of the left hand side of the operator, which in your case is 0. Since 0 is false in c, then the right hand side expression of the operation, (a = b = 777), is never evaluated.
The second case is similar, except that || returns true if the left hand side expression returns true. Also remember that in c, anything that is not 0 is considered true.
Hope this helps.
Another trap in this expression is that; the precendence of the operators. Such as &&, || (logical and, logical or) operators have higher precedence to the assignment operator(=).
in this case x=(0&&(a=b=777)) is same as x=0&&(a=b=777), however x=(0&(a=b=777)) is more readable than the previous one.
Logical operators select one of their operands and returns the result accordingly.
They also force their operands to be boolean as true or false.
In this expression "x=0&&(a=b=777)" since the first operand is false the result will be equal to first operand.Second operand is short circuited and will not be executed.So the output will be a=b=0, x=0.
x=777 || (a=++b) in this expression since the first operand is true the result will be equal to the first operand and logical operator will not check the second operand, logical OR operator will bypass the second operand.In this expression since the first operand is true (777 is converted to true) the result will be True means x=1.Since the second operand is skipped "a" and "b" values will remain same as their previous values, in this case 0,0
This question already has answers here:
C operator precedence, logical vs unary in a++ && b++ || ++c
(1 answer)
Require explanation for the output
(4 answers)
Precedence of && over || [duplicate]
(4 answers)
Closed 3 years ago.
I want so see the values of the four variables (Basically checking the precedence order of logical operators).
#include<stdio.h>
int main()
{
int a=0, b=-7, c=0, d;
d = ++c || ++a && ++b ;
printf("\n %d %d %d %d",a,b,c,d);
}
I expect the result to be '0 -6 1 1', but the actual output is '0 -7 1 1'. Can anyone please give an explanation behind the output shown?
First have a look at Operator Precedence.
Then, regarding the working of logical OR operator, from C11, chapter ยง6.5.14 (emphasis mine)
[...] 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.
and regarding the result:
The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it
yields 0. The result has type int.
So, in your code
d = ++c || ++a && ++b ;
is the same as
d = (++c) || (++a && ++b);
which evaluates to
d = 1 || (++a && ++b); // short circuit, RHS not evaluated
which is finally same as
d = 1; // 1 is not the value computation of `++c`, rather result of the `||` operation.
I'm studying C from A Book on C by Kelley-Pohl, and there's this exercise that I don't understand:
int a = 0, b = 0, x;
x = 0 && (a = b = 777);
printf("%d %d %d\n", a, b, x);
x = 777 || (a = ++b);
printf("%d %d %d\n", a, b, x);
They just say to imagine the output and compare it to the real one. I thought the output would have been
777 777 0
778 778 1
but it is
0 0 0
0 0 1
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.
In this expression statement
x = 0 && (a = b = 777);
the first operand compares equal to 0. So the second operand is not evaluated that is the values of the variables a and b are not changed. So the variable x will be set to 0 according to the paragraph #3 of the section.
From the C Standard (6.5.14 Logical OR operator)
3 The || operator shall yield 1 if either of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
and
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.
In this expression statement
x = 777 || (a = ++b);
the first operand compares unequal to 0. So the second operand is not evaluated that is the values of the variables a and b are not changed.. So the variable x will be set to 1 according to the paragraph #3 of the section.
If you will change the order of the operands in the expressions like
x = (a = b = 777) && 0;
x = (a = ++b) || 777;
you get the expected by you result.
The && operator uses lazy evaluation. If either side of the && operator is false, then the whole expression is false.
C checks the truth value of the left hand side of the operator, which in your case is 0. Since 0 is false in c, then the right hand side expression of the operation, (a = b = 777), is never evaluated.
The second case is similar, except that || returns true if the left hand side expression returns true. Also remember that in c, anything that is not 0 is considered true.
Hope this helps.
Another trap in this expression is that; the precendence of the operators. Such as &&, || (logical and, logical or) operators have higher precedence to the assignment operator(=).
in this case x=(0&&(a=b=777)) is same as x=0&&(a=b=777), however x=(0&(a=b=777)) is more readable than the previous one.
Logical operators select one of their operands and returns the result accordingly.
They also force their operands to be boolean as true or false.
In this expression "x=0&&(a=b=777)" since the first operand is false the result will be equal to first operand.Second operand is short circuited and will not be executed.So the output will be a=b=0, x=0.
x=777 || (a=++b) in this expression since the first operand is true the result will be equal to the first operand and logical operator will not check the second operand, logical OR operator will bypass the second operand.In this expression since the first operand is true (777 is converted to true) the result will be True means x=1.Since the second operand is skipped "a" and "b" values will remain same as their previous values, in this case 0,0