Translating C to C — Expressions with relational and logical operators

C and Java have six relational operators (==, !=, <, <=, >, >=) and four logical operators (&&, ||, !, ? :). In Java all of these return booleans, true or false. In C and C++, these operators return an integer, 1 for true and 0 for false. When evaluating logical operators, C considers any non-zero value to be true. This means that all of the following expressions have the value 1 in C and C++.

The MIPS32 architecture has a four instructions, SLT, SLTI, SLTIU, and SLTU, that can be used to implement the < operator. However, most compilers will use branch instructions, which resemble the if, when implementing the relational and logical operators.

Evaluation of relational operators

In hardware the test of x <y is usually accomplished by subtracting y from x and testing if the result is less than 0. The table below illustrates how this transformation is made for the six relational operators.

x == y x-y == 0
x != y x-y != 0
x < y x-y < 0
x <= y x-y <= 0
x > y x-y > 0
x >= y x-y >= 0

As you will see in a few days, rarely does the C compiler actually store the result of relational operator because programmers just don’t do that very often (or don’t do that as often as they should). But suppose an assignment like the following does appear in a program.

τ = x != y ;

Most likely it would be implemented by something similar to the following C code.

τ = 0 ;
if (x - y != 0) {
  τ = 1 ;
}

Evaluation of logical operators

The logical not operator of C is easy. It can be implemented with a relational operator. Every instance of can be transformed to τ!=0.

The other three logical operator of C (and Java) are short circuit operators. They may not evaluate all of their operands before yielding a result. These operators are &&, ||, and the ? : ternary operator. They can be implemented using C’s if construct using the control structure rules if they are first translated into ifelse statements. The following table shows the translation rules for these logical operators. Study them to make sure you see where the short cut is taken.

τ = exp1 && exp2 ;

if (! (exp1))
   τ = 0 ;
else if (! (exp2))
   τ = 0 ;
else
   τ = 1 ;

τ = exp1 || exp2 ;
if (exp1)
   τ = 1 ;
else if (exp2)
   τ = 1 ;
else
   τ = 0 ;
τ = exp1 ? exp2 : exp3 ;

if (exp1)
   τ = exp2 ;
else
   τ = exp3 ;

Also, make sure you understand why the short circuit is needed in a Java expression like the following:

done = x < 0 || x >= A.length() || A[x] < 0 ;