views:

158

answers:

5

Consider this expression as a "selection" control structure on integer "x": 0 < x < 10, with the intention that the structure returns TRUE if "x" is in the range 1..9.

  1. Explain why a compiler should not accept this expression. (In particular, what are the issues regarding the binary operator "<"?
  2. Explain how a prefix operator could be introduced so the expression can be successfully processed.
+2  A: 
  1. 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.

  2. 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.

JB King
< *is* a binary operator, the expression is not a binary *operation*.
Clifford
Ok, corrected terminology in my answer.
JB King
+1  A: 

Consider the return types of the < operator.

Donnie
And specifically, how the expression is evaluated, and in what order. Write down the series of steps that the compiler must take to evaluate the expression, and the value at each one of those steps.
WhirlWind
A: 

I see no reason why this mysterious compiler couldn't transform that expression into:

x > 0 && x < 10 
ChaosPandion
I could tell you why, but that would give the answer to the homework! Your expression is not semantically the same; at least not in C or C++
Clifford
@Clifford, Who said this is C or C++?
JSBangs
@Clifford - Please explain why. *(By the way I simply meant to write this in a syntax that most people would understand. I make no claims at being an expert.)*
ChaosPandion
@JS Bangs: No one, but the answer is language dependent, so the question is unanswerable unless and until we are told. My point was that ChaosPandion sees "no reason", but one reason might be because it is a C++ compiler.
Clifford
@ChaosPandion: I think that is the point of the question, one might think they are equivalent, but in many programming languages they are not, so the compiler could not "transform" it, you have to write semantically correct code (i.e. it has to mean to the compiler what you intended) not just syntactically correct. I have added an answer that perhaps explains the problem without giving away too much.
Clifford
A: 

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.

Clifford
A: 

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);
        }
    }
}