17

In an if statement I want to include a range, e.g.:

if(10 < a < 0)

but by doing so, I get a warning "Pointless comparison". However, this works fine without any warning:

if(a<10 && a>0)

Is the first case possible to implement in C?

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
jscode
  • 193
  • 1
  • 1
  • 6

6 Answers6

43

Note that the original version if(10 < a < 0) is perfectly legal. It just doesn't do what you might (reasonably) think it does. You're fortunate that the compiler recognized it as a probable mistake and warned you about it.

The < operator associates left-to-right, just like the + operator. So just as a + b + c really means (a + b) + c, a < b < c really means (a < b) < c. The < operator yields an int value of 0 if the condition is false, 1 if it's true. So you're either testing whether 0 is less than c, or whether 1 is less than c.

In the unlikely case that that's really what you want to do, adding parentheses will probably silence the warning. It will also reassure anyone reading your code later that you know what you're doing, so they don't "fix" it. (Again, this applies only in the unlikely event that you really want (a < b) < c).)

The way to check whether a is less than b and b is less than c is:

a < b && b < c

(There are languages, including Python, where a < b < c means a<b && b<c, as it commonly does in mathematics. C just doesn't happen to be one of those languages.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • With some compilers, saying `(a < b) < c` still gives a warning: comparing the output of a binary boolean with int. You have to say `(int) (a < b) < c`. :) – Alex Jun 21 '17 at 14:27
  • @Alex: No, you don't have to. Compilers can warn about anything they like, but `(a < b) < c` is a valid expression with well defined semantics. The cast just converts an expression that's already of type `int` to type `int`. What compiler warns about it, and what is the warning? (gcc and clang don't.) – Keith Thompson Jun 21 '17 at 16:34
6

It's not possible, you have to split the check as you did in case 2.

user703016
  • 37,307
  • 8
  • 87
  • 112
5

No it is not possible.
You have to use the second way by splitting the two conditional checks.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
2

The first does one comparison, then compares the result of the first to the second value. In this case, the operators group left to right, so it's equivalent to (10<a) < 0. The warning it's giving you is really because < will always yield 0 or 1. The warning is telling you that the result of the first comparison can never be less than 0, so the second comparison will always yield false.

Even though the compiler won't complain about it, the second isn't really much improvement. How can a number be simultaneously less than 0, but greater than 10? Ideally, the compiler would give you a warning that the condition is always false. Presumably you want 0<a<10 and a>0 && a<10.

You can get the effect of the second using only a single comparison: if ((unsigned)a < 10) will be true only if the number is in the range 0..10. A range comparison can normally be reduced to a single comparison with code like:

if ((unsigned)(x-range_start)<(range_end-range_start))
    // in range
else
    // out of range.

At one time this was a staple of decent assembly language programming. I doubt many people do it any more though (I certainly don't as a rule).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Note that meanwhile, the question has been edited in such a way that the second paragraph of your answer has been invalidated. – Andreas Wenzel Jan 22 '23 at 20:46
0

As stated above, you have to split the check. Think about it from the compiler's point of view, which looks at one operator at a time. 10 < a = True or False. And then it goes to do True/False < 0, which doesn't make sense.

Steve
  • 4,457
  • 12
  • 48
  • 89
  • i dont think that if statement will even check that true/false<0 or not,even if it make sense or not...lols..:D – nobalG Aug 05 '11 at 19:41
-2

no,this is not valid syntax of if statement,it should have a valid constant expression,or may have logical operators in them,and is executed only,when the expression in the bracket evaluates to true,or non zero value

nobalG
  • 4,544
  • 3
  • 34
  • 72
  • 2
    It is valid syntax; see my answer. – Keith Thompson Aug 05 '11 at 19:39
  • 1
    It is valid syntactically, it just doesn't mean what the questioner hoped it would mean. – Steve Jessop Aug 05 '11 at 19:40
  • @Alfred Nobel: Depends on what you mean by "work". It's equivalent to `if (1 < 13)`, which is true. By sheer coincidence, it happens to yield the same result as `if (10 < 12 && 12 < 13)`. (I can imagine this kind of thing creating a bug that goes undiscovered for years.) – Keith Thompson Aug 05 '11 at 19:53
  • then if(11>12<10) will yield true,& is equivalent to if(11>12 && 12<10) will yield false......how such kind of shit statement are allowed then... @keith thompson – nobalG Aug 05 '11 at 20:00
  • @Alfred Nobel: No, `(11 > 12 < 10)` is *not* equivalent to `(11 > 12 && 12 < 10)`; that's the whole point. It might be nice if they were equivalent (and I think there are languages where they are). But *either* forbidding expressions like `(a < b < c)` *or* making them equivalent to `(a < b && b < c)` would (1) make the language rules more complex, and (2) risk breaking existing code in a language that's been around for decades. What solution do you suggest? – Keith Thompson Aug 05 '11 at 20:09
  • @keith thompson: sir! then we are left with only 1 option,DON'T USE THESE TYPE OF EXPRESSIONS IN IF....:D....I was very curious about this question as i got my first -1,from this answer – nobalG Aug 05 '11 at 20:49
  • 1
    @Alfred Nobel: I completely agree; expressions like `(a < b < c)` should be avoided because they're too confusing. Even if you know exactly what they mean, you can't be sure that the author did. (For the record, I didn't downvote you, but whoever did probably did so because you incorrectly said it's "not valid syntax".) – Keith Thompson Aug 05 '11 at 21:10