Skip to end of metadata
Go to start of metadata

The relational and equality operators are left-associative in C. Consequently, C, unlike many other languages, allows chaining of relational and equality operators. Subclause 6.5.8, footnote 107, of the C Standard [ISO/IEC 9899:2011], says:

The expression a<b<c is not interpreted as in ordinary mathematics. As the syntax indicates, it means (a<b)<c; in other words, "if a is less than b, compare 1 to c; otherwise, compare 0 to c."

These operators are left-associative, which means the leftmost comparison is performed first, and the result is compared with the rightmost comparison. This syntax allows a programmer to write an expression (particularly an expression used as a condition) that can be easily misinterpreted.

Noncompliant Code Example

Although this noncompliant code example compiles correctly, it is unlikely that it means what the author of the code intended:

int a = 2;
int b = 2;
int c = 2;
/* ... */
if (a < b < c) /* Misleading; likely bug */
/* ... */
if (a == b == c) /* Misleading; likely bug */

The expression a < b < c evaluates to true rather than, as its author probably intended, to false, and the expression a == b == c evaluates to false rather than, as its author probably intended, to true.

Compliant Solution

Treat relational and equality operators as if it were invalid to chain them:

if ( (a < b) && (b < c) ) /* Clearer and probably what was intended */
/* ... */
if ( (a == b) && (a == c) ) /* Ditto */

Risk Assessment

Incorrect use of relational and equality operators can lead to incorrect control flow.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

EXP13-C

Low

Unlikely

Medium

P2

L3

Automated Detection

Tool

Version

Checker

Description

Astrée
19.04
chained-comparisonFully checked

ECLAIR

1.2

CC2.EXP13

Fully implemented

GCC
4.3.5


Option -Wparentheses warns if a comparison like x<=y<=z appears; this warning is also enabled by -Wall

LDRA tool suite
9.7.1
433 SFully implemented
Polyspace Bug Finder

R2018a

Possibly unintended evaluation of expression because of operator precedence rules

Operator precedence rules cause unexpected evaluation order in arithmetic expression

PRQA QA-C
9.5

3392
3401
4111
4112
4113

Fully implemented
PVS-Studio

6.23

V709
RuleChecker
19.04
chained-comparisonFully checked

Related Guidelines

Bibliography

[ISO/IEC 9899:2011]Subclause 6.5.8, "Relational Operators"



2 Comments

  1. A couple of questions:

    1. What does "left-associatvie" mean in C? What's the definition in C spec?
    2. Is is true that in other languages, relational (or equality) operators are associative?

    1. Added some text to address your first question..

      I think most operators are left-associative in most languages by default; that's the easiest way to parse source code. (Some languages choose features to be right-associative, but that's a conscious decision).

      But Java doesn't allow relation chaining (eg a<b<c). It's not forbidden by 'associativity', but rather by Java being more strongly typed than C. It's still parsed as ((a<b)<c), but (a<b) is a boolean type, and the relation operators cannot be applied to boolean types, so a<b<c generates a type mismatch error. I'd guess most langauges that disallow chaining use a similar strategy. C allows this because (a<b) returns an int type (which has the value 0 or 1).