Came across some code that has an OR operator (||) in the return line. Could someone explain what that does ?
Here's something that looks like it:
int main()
{
...
return (1 || 0);
}
But really it was a function (that returned 1 or 0) instead of the 1 and 0:
int main()
{
...
return (foo(x++, y) || foo(x, y++));
}
a || b evaluates to 1 if a is non-zero irrespective of the value of b, evaluates to 1 if a is 0 and b is non-zero, else it's 0.
So 1 || 0 is 1, as would be 2 || 0.
Note that b is not evaluated if a is non-zero: so if b was a function, it would not be called in such a case. So in your example, foo(x, y++) is not called including the evaluation of y++ if foo(x++, y) is non-zero.
Note that the type of a || b is an int irrespective of the type of the arguments. Cf. C++ where the type is a bool.
Logical OR has a short circuit property. The RHS is only evaluated if the LHS is evaluated to false.
In this case, since the operands are function call, so
the LHS function call foo(x++, y) will be made.
If the return value is 1 (TRUTHY), the RHS will not be evaluated and the value 1 will be returned.
If the returned value is 0, the foo(x, y++) function call with made, and the return value will be based on teh return value of the function call.
Related
This question already has answers here:
Logical equality in C
(4 answers)
Closed 3 years ago.
What does
return x == y;
mean?
What does
return x == y;
mean?
Do a logical comparison between x and y which evaluates to an int holding either 1 or 0 depending on x and y being equal or not.
End the function and return the result as per 1..
First of all, let me make you understand what x == y means.
x == y compares x and y. The result of x == y will be true if x and y are equal, false otherwise.
In C, true is equivalent to any non-zero value (default is 1) and false is equivalent to zero.
So, if x is equal to y, x == y is equal to 1. Otherwise it is 0.
Finally, return x == y means that the value returned by the function will be 1 if both x and y are equal, 0 otherwise.
Consider the function,
int isEqual(int x, int y) {
return x == y;
}
int main() {
printf("%d", isEqual(1, 1)); // 1
printf("%d", isEqual(1, 2)); // 0
return 0;
}
== compares values of two variables. The compare results in true or false, so if x and y are equal, the result is true, else the result is false.
The return statement returns this result from the function.
In C, false is represented for a 0, and true for each other number (positives and negatives). So the function returns a 0 or a 1
According to the C Standard (6.5.9 Equality operators)
3 The == (equal to) and != (not equal to) operators are analogous to
the relational operators except for their lower precedence.108) Each
of the operators yields 1 if the specified relation is true and 0 if
it is false. The result has type int. For any pair of operands,
exactly one of the relations is true.
So in this return statement
return x == y;
there is used an expression with the equality operator ==. The value of the expression either 1 or 0 depending on whether x is equal to y or not. So the return statement returns either 1 or 0.
You could rewrite the return statement like
int result = ( x == y );
return result;
Consider for example an if statement in the condition of which there are compared two strings
if ( strcmp( s1, s2 ) == 0 )
{
puts( "The strings are equal each other." );
}
//...
You could write a separate function that would look like
int equal( const char *s1, const char *s2 )
{
return strcmp( s1, s2 ) == 0;
}
In this case the if statement would look like
if ( equal( s1, s2 ) )
{
puts( "The strings are equal each other." );
}
//...
The expression x == y yields an integer value, either 0 (when x is not equal to y) or 1 (when x is equal to y).
This gives you a bool (or boolean). If x is equal to y, it will return true, if not, then false. This will work the same in most programming languages that use the == operator.
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).
I was taking a practice programming quiz, and I'm not sure why this program prints out -1:
#include <stdio.h>
int main()
{
int x = 1;
if (x-- && x-- && x--)
{
printf("%d\n", x);
} else
{
printf("%d\n", x);
}
return 0;
}
In C, logical operators such as && and || are evaluated using short-circuit evaluation, which essentially means that when a statement is guaranteed to be either true or false, any subsequent expressions in the statement are not evaluated.
In your program, only the first two conditions need to be evaluated to determine that the whole statement is false. The third expression is not evaluated.
if (x-- && /* evaluates true, and then x is decremented */
x-- && /* evaluates false, and then x is decremented */
x--) /* this is not executed */
Because this is a series of AND statements, logically, only one expression needs to be false for the whole statement to be false. When the second expression is determined to be false, there's no need to waste resources by evaluating the rest of the statement, so the else block is executed.
This causes the final value of x to be -1, instead of -2.
In C language, the test statement would end its operation as soon as the result can be determined. In this case, the first x-- returns 1 and set x = 0, the second x-- returns 0 and set x = -1.
1 && 0 can determine the result as 0, so the last x-- is ignored.
With a FALSE statement, the if-else choose the second printf as output and print the value of x : -1;
First start with x = 1, then the sequence of x-- && x-- && x-- goes like this, where each x-- represents the respective part of the condition.. (note that && acts as a sequence point).
x = 1 -> x = 1
x-- -> 1, x = 0
The result is 1 (1 && x-- && x--) so right-hand express of the first && is evaluated.
x-- -> 0, x = -1
The result is 0 (1 && 0 && x--) and the && short-circuit evaluation kicks in and the right-hand expression of the second && is not evaluated.
x--
Nope; as above this was not evaluated.
Since the condition is false (1 && 0 && dont_care_not_evaluated) it prints out the value, in the else case, while having only decremented x twice.
x-- -> 1-- it returns 1 here, after it gets decrements to 0
x-- -> 0-- it returns 0 here, what means false, after it gets decremented x to
x-- -> its unreahched, because this is an and condition, it stops if a part of it is false
so the final value will be -1 (what is not 0, so -1 is interpreted as true)
Since the associativity of '?' is from right to left,any 2 consecutive '?' operators must be treated as such,Right?
Now,
int x=-1;
int y=x?x++?x:-1:1;
I expect this to be executed as:
int y = x ? (x++?x:-1) : 1;
Now since its being executed from right to left,when encountering the first '?' in the statement,x's value is 0 and the expression is as
int y= x? 0 : 1;
hence i expected y to be 1,but it shows Zero on my dev-cpp.Where am i wrong?
You have the order of evaluation wrong. In a ? b : c, a is always evaluated first, then either b or c is evaluated.
I've marked up your example so that I can identify subexpressions:
c
int y=x?x++?x:-1:1;
a bbbbbbbb
(a) is evaluated, yielding -1, so (b) is evaluated. There, x++ is evaluated, yielding -1 again, so (c) is evaluated. At this point, x is 0.
Or, with more verbose, clearer code, it's as if you said:
int x = -1;
int y;
if (x != 0)
{
int new_x = x + 1;
if (x != 0)
{
y = new_x;
}
else
{
y = -1;
}
}
else
{
y = 1;
}
Operations:
Assign y to value =
if(x): --> x = -1, so true as it is non-zero
{
if(x): --> x = -1 ,so true as x will increment later due to post increment
x= x +1; --> increment x, so x = 0 . This is the value assigned. So y = 0;
else:
-1
}
else:
{
1
}
Hope this helps!
The answer to your question is that in C/C++ int y = x ? (x++?x:-1) : 1; we will hit two sequence points at ?. Any update operations to variable with in a sequence point will be effective after that sequence is over. So lets look at our example in hand.
First sequence point is first ? from left.
x=-1; (Actual Value)
x=-1; (Value used in expression)
y=-1?(x++?x:-1):1;
Second sequence point is second ? from left. As mentioned above the update operations are effective after sequence so even though x++ is there the value used in this sequence is -1 and updated value will be used in following.
x=0; (Actual Value, bcoz of x++)
x=-1; (Value used in expression)
y=-1?x:-1;
Now it will be
x=0; (Actual Value)
x=0; (Value used in expression)
y=x;
y=0;
Hope this make sense now.
I don't know if anyone could kindly explain this code for me?
unsigned int x = 0;
(x ^= x ) || x++ || ++x || x++;
printf("%d\n", x);
when I compile this on my computer using gcc 4.2, the output is 2.
Originally i thought maybe this behavior is unspecified but then i figure || will have lower precedence over other operators, so shouldn't the answer be 3? Since there are three "++".
Can someone explain? Thanks
(x ^= x) is evaluated and it yields 0, therefore:
(x++) is evaluated and it yields 0, therefore:
(++x) is evaluated and it yields 2, therefore it stops
It all boils down to one rule: || only evaluates its right side if its left side is false.
The issue is that the || operator is short-circuiting. As soon as it finds a true value, it no longer needs to check the remaining || statements; the answer is already known.
(x ^= x) evaluates to 0.
x++ evaluates to 0, then increments x to 1.
++x evaluates to 2 -- true.
The final or statement does not need to be computed. It "short-circuits" and immediately returns true.
The behaviour is well-defined. You are observing the short-circuiting behaviour of ||; the final x++ is never evaluated.
That is short-circuit semantics in action. The first expression x ^= x evaluates to 0, the second evaluates to 0 as well. The third one evaluates to 2, and then the logical expression is short-circuited since its result its already determined to be true.
Of course you shouldn't use such constructs, but let us analyze the expression.
There are 4 expressions combined with shortcut-OR:
a || b || c || d
b, c and d are only evaluated, if a is false, c and d only if b is false too, and d only if all from the before are false.
Ints are evaluated as 0 == false, everything else is not false.
x ^= 0
with x being 0 is 0 again.
x++
is evaluated and later increased, so it evaluates to 0, which invokes expression c, but later x will be increased.
++x
is first incremented, leading to 1, and then evaluated (leading to 1) which is the reason, why d is not evaluated, but the increment of b is pending, so we get 2.
But I'm not sure, whether such behaviour is exactly defined and leads to the same result on all compilers.
Avoid it.
The expressions between the || operators will be evaluated left to right until one is true:
(x ^= x )
Sets all bits in x to 0/off. (false);
x++
Increments x, it's now 1, but still false because this was a post increment.
++x
(pre-)Increments x, which is now 2 and also true, so there is no need for the right hand side of || to be evaluated.