Consider this expression as a "selection" control structur开发者_开发知识库e on integer "x": 0 < x < 10, with the intention that the structure returns TRUE if "x" is in the range 1..9.
- Explain why a compiler should not accept this expression. (In particular, what are the issues regarding the binary operator "<"?
- Explain how a prefix operator could be introduced so the expression can be successfully processed.
The expression doesn't read like a binary operation, but resembles a ternary operator. There are 3 parameters to what you have stated with 0 < x < 10, as 0,x, and 10 are all tokens for the parser to interpret, no? If you meant for a pair of < to form a ternary operator that is a different story.
One could view the ternary operation as getting split into a pair of comparisons and each comparison is evaluated with the results combined by an AND operation. That would make sense to my mind.
Consider the return types of the < operator.
I see no reason why this mysterious compiler couldn't transform that expression into:
x > 0 && x < 10
The code is syntactically valid in C and C++, but is unlikley to be semantically correct in either language. We are left guessing the language at this time.
When I compiled it as C++ VC++2008 issued a warning which rather gave away the answer, so you might try that. Here's my test code:
int main()
{
volatile int x = 0 ;
if( x < x < 10 )
{
x = 5 ;
}
}
When C compilation was used it accepted it silently.
As to why it may be a problem, the compiler interprets the expression as (0 < x) < 10. Hint: what is the type of the left-hand side of the second "<" ?
However this may not be the answer you are looking for, because it seems that you must be referring to a different language if the compiler should not accept it.
C++ is happy with it. You can even give it the right semantics:
#include <iostream>
#include <cstdlib>
#include <cassert>
using namespace std;
class Int
{
public:
int x;
Int () { }
Int (int z) : x (z) { }
};
class BoolRange
{
public:
bool value;
int left;
int right;
BoolRange() : value (false) { }
BoolRange (bool v, int l, int r)
: value (v), left (l), right (r) { }
operator bool ()
{
return value;
}
};
ostream& operator<< (ostream& out, Int i)
{
return out << i.x;
}
ostream& operator<< (ostream& out, BoolRange b)
{
return out << b.left << '[' << b.value << ']' << b.right;
}
BoolRange operator< (Int l, Int r)
{
return BoolRange (l.x < r.x, l.x, r.x);
}
BoolRange operator< (Int l, BoolRange r)
{
return r.value
? BoolRange (l.x < r.left, l.x, r.right)
: BoolRange ();
}
BoolRange operator< (BoolRange l, Int r)
{
return l.value
? BoolRange (l.right < r.x, l.left, r.x)
: BoolRange ();
}
BoolRange operator< (BoolRange l, BoolRange r)
{
return l.value && r.value
? BoolRange (l.right < r.left, l.left, r.right)
: BoolRange ();
}
// Test driven development!
int main ()
{
for (int i = 0; i < 1000000; ++i)
{
Int v = rand() % 100;
Int w = rand() % 100;
if (Int(1) < v < w < Int(10)) // Look here!
{
assert (1<v.x && v.x<w.x && w.x<10);
} else
{
assert (1>=v.x || v.x>=w.x || w.x>=10);
}
}
}
精彩评论