Is that a valid expression? If so, can you rewrite it so that it makes more sense? For example, is it the same as (4 > y && y > 1)? How do you evaluate chained logical operators?
-
Possible duplicate of [Language support for chained comparison operators (x < y < z)](https://stackoverflow.com/questions/4090845/language-support-for-chained-comparison-operators-x-y-z) – phuclv Feb 10 '18 at 10:01
5 Answers
The statement (4 > y > 1) is parsed as this:
((4 > y) > 1)
The comparison operators < and > evaluate left-to-right.
The 4 > y returns either 0 or 1 depending on if it's true or not.
Then the result is compared to 1.
In this case, since 0 or 1 is never more than 1, the whole statement will always return false.
There is one exception though:
If y is a class and the > operator has been overloaded to do something unusual. Then anything goes.
For example, this will fail to compile:
class mytype{
};
mytype operator>(int x,const mytype &y){
return mytype();
}
int main(){
mytype y;
cout << (4 > y > 1) << endl;
return 0;
}
- 464,885
- 45
- 335
- 332
-
9Technically, `4 > y` returns either `false` or `true`, which are the converted to `0` or `1` for the next comparison. – fredoverflow Jan 17 '12 at 06:16
-
I'd label the parse as `operator>(operator>(4, y), 1)` to emphasise the fact that it's repeated application of binary functions, rather than some kind of n-ary function – Caleth Nov 05 '18 at 16:25
-
C++ needs stronger types. Implicit type conversion leads to such subtle bugs. – Vasantha Ganesh Mar 15 '21 at 12:30
Expression Validity
Yes, it is a valid expression, assuming y is, or can be implicitly converted into, an integer. If it is not and the > operator is overloaded, it's a different story outside the scope of this question.
It will be evaluated left to right as ((4 > y) > 1).
Assuming y is an integer, let's consider the two possibilities. 4 > y can return true or false. The next part effectively becomes true > 1 or false > 1.
Given the implicit bool to int conversion, there are two possibilities:
A) 4 > y returns true. true evaluates to 1. 1 > 1 evaluates to false.
B) 4 > y returns false. false evaluates to 0. 0 > 1 evaluates to false.
No matter what, the expression will evaluate to false.
Rewritten Interpretation
I assume what you intend is ((4 > y) && (y > 1)).
Example
(4 > y > 1) is not the same as (4 > y && y > 1).
Logical Operators
The logical operators (!, &&, ||) use short-circuiting logic.
Given a && b, a will be evaluated. If a evaluates to true, then b will be evaluated. Else, b will not be evaluated. As for a || b, short-circuiting logic works in reverse. a will be evaluated. Since expression a is evaluated first, if it is false, there is no possibility that the entire expression will evaluate true.
Given a || b, a will be evaluated. If a evaluates to false, then b will be evaluated. Else, b will not be evaluated. Since expression a is evaluated first, if it is true, there is no possibility that the entire expression will evaluate false.
Chaining the operators is a matter of operator precedence. Better to use parentheses and be clear rather than risk the wrong behavior.
- 1
- 1
- 4,057
- 2
- 21
- 37
I think it's a valid expression (not a statement), but probably doesn't do what you want. It evaluates left-to-right, as (4 > y) > 1. The test 4 > y will evaluate to either 0 (false) or 1 (true), and the entire expression will always evaluate to 0 (false).
- 232,168
- 48
- 399
- 521
4 > y will evaluate to a boolean value of true or false. The remainder of the expression is then essentially [true|false] > 1, which does not make sense.
- 846
- 2
- 7
- 20
-
It "makes sense" when you realize that `true` and `false` are integer values in C/C++. – Ted Hopp Jan 17 '12 at 04:16
-
2
-
@Gman: A technicality, but a relevant one. Semantics can be cruel. – Sion Sheevok Jan 17 '12 at 04:36
4 > y > 1 --> MAY BE ANYWAY if y - is class!!.
#include <iostream>
#include <string>
struct num{ int n; };
struct op{ bool v; struct num n; };
struct op operator > (int x, num n){
struct op o = { x > n.n, n };
return o;
}
bool operator > (struct op o, int x)
{
return o.v && o.n.n > x;
}
int main()
{
struct num y = { 2 } ;
if ( 4 > y > 1 ) { std::cout << "4 > y > 1 TRUE" << std::endl; }
else { std::cout << "4 > y > 1 ALWAYS FALSE" << std::endl; }
}
- 866
- 8
- 15