3

I was messing around a bit in C while making a function, and somehow ended up with a comparison like this:

if (sizeAllocated > type_get_binary_size(data) > spaceAvailable)

The (for me) unexpected thing was that this compiled without so much as a warning (using IAR compiler for ARM, C99 standard with IAR extensions).
This doesn't look like it should be valid C (at least it's not a valid comparison in any other languages I can think about at the moment), can some gurus help me shed some light on whether this is some IAR-specific quirk or if it's actual standard C that's just too obscure to be included in any common tutorials?

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
ToVine
  • 560
  • 5
  • 16
  • 1
    [Why does (0 < 5 < 3) return true?](http://stackoverflow.com/q/4089284/995714), [Language support for chained comparison operators (x < y < z)](http://stackoverflow.com/q/4090845/995714) – phuclv Jul 28 '16 at 17:41
  • I tried searching before posting the question but didn't find those, thanks @LưuVĩnhPhúc! :) – ToVine Jul 28 '16 at 17:43
  • It is a valid **expression**. Whether it is a valid **comparsion** depends on what you expect it to do. – too honest for this site Jul 28 '16 at 19:10
  • You might want to enable more warnings, `gcc -Wall -W` or `clang -Weverything` – chqrlie Jul 28 '16 at 20:55
  • @chqrlie if only I could use GCC or Clang... More warnings might be a good idea though – ToVine Jul 28 '16 at 23:18
  • You can install `gcc` on a Windows system with `cygwin` or `MinGW`. You can get more warnings from Visual C++ with `/W4` or something like that. – chqrlie Jul 28 '16 at 23:41
  • @chqrlie "using IAR" - I really wouldn't use a compiler costing several thousand dollars per year (or even windows for that matter) unless I had no other choice, but thanks for the tip anyway. – ToVine Jul 29 '16 at 06:41

2 Answers2

4

This is valid code, but it won't do what you expect.

The > operator is left-associative, so the expression effectively becomes:

((sizeAllocated > type_get_binary_size(data)) > spaceAvailable)

The inner portion will evaluate to 0 if the condition is false or 1 if the condition is true. This value is then compared against spaceAvailable.

In C, the results of a comparison operator have an integer type, so comparing this result to an integer is valid.

So what you're actually doing is either 0 > spaceAvailable or 1 > spaceAvailable, depending on how the first conditional evaluates.

What you probably want is this:

int size = type_get_binary_size(data);
if ((sizeAllocated > size) && (size > spaceAvailable))

Note that the function call is done first before the if so it isn't called twice in the conditional.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Wow - that's not really what I expected, and you're right about what I intended. IMO that would be a more useful behavior; if I wanted the `((sizeAllocated > type_get_binary_size(data)) > spaceAvailable)` comparison I'd have written it with parenthesis anyway. Thanks for the clarification! – ToVine Jul 28 '16 at 17:47
  • I suspect OP needs `if ((sizeAllocated >= size) && (size >= spaceAvailable))` (>= vs >) – chux - Reinstate Monica Jul 28 '16 at 18:59
  • @chux no, `>` was right in this case (not that it would matter to the question though) – ToVine Jul 29 '16 at 06:44
2

The > operator is left-associative, so A > B > C is parsed as (A > B) > C. A > B evaluates to 0 or 1, so you're basically comparing 0 > C or 1 > C.

John Bode
  • 119,563
  • 19
  • 122
  • 198