Return value of C boolean expression

The C language is not of type Boolean; instead, it uses integers. comparison operators such as == and <= return the integer value 0 for false and 1 for true. However, the if statement in C considers any nonzero value of its condition to be true. Why is the difference? Why not let relational operators return any nonzero value to represent true?

+7
c boolean-expression
source share
4 answers

I believe that this was an arbitrary decision, returning to the language of the ancestors of B.

Quoting Link for users to B :

The relational operators < (less than), <= (less than or equal to), > (more) and >= (greater than or equal) take integer rvalue values. The result is one if the operands are in this relation to each other. Otherwise, the result is zero.

There is no explanation for this particular choice and no explanation in ANSI C Justification or the 1978 edition of Kernigan and Ritchie's book The C Programming Language (K & R1).

(In the BCPL of the ancestral language, it had true and false literals, and true represented with all bits set to 1 )

A language could be defined in different ways, and it would still be internally consistent. For example, a standard might say that relational and equality operators result in 0 if the condition is false or any arbitrary non-zero value if the condition is true. The result could be correctly used in the if or in any other context that requires a condition. And it’s easy to imagine a processor on which it is more efficient so that the true value is represented as β€œall-bit-one”, and not as 1 , but the language standard does not allow this.

Several standard library functions, such as isdigit() , can return any arbitrary non-zero value to indicate a true condition, which once again demonstrates that it was an arbitrary choice. ( isdigit , of course, is implemented through a table search, which can give values ​​other than 0 and 1 ).

There is some added benefit in that equalities and relational operators give 0 and 1 . For example, this simplifies the calculation of the number of conditions:

 int count = 0; count += x == y; count += foo > bar; count += this <= that; 

I assume it was convenient to use 0 and 1 in the first B compiler, the behavior was documented, and it has been inherited to this day. Changing the definition would result in the loss of code depending on the previous definition.

And even if it is relatively inefficient in some systems, this is not a huge problem. The result of an equality or relational operator is usually not stored anywhere, so the compiler can present the result, but it likes it so long as the behavior is incompatible. In some cases, it may be necessary to generate code to normalize the result to 0 or 1 , but this is unlikely to be significant.

+5
source share

If a conditional expression can return any non-zero value for true, you may encounter difficulties in storing it in a too small variable, in the extreme case a one-bit bit field.

 struct foo { unsigned int bar: 1; } baz; baz.bar = 1 == 1; 

If condition 1 == 1 was returned 2 (or any even number), you will have problems, since baz.bar will end with 0 , which will be evaluated as false in a boolean context.

+3
source share

When you use a relational operator inside a conditional expression, the compiler is going to compile it into a "jump if it is larger" or similar operator, and does not bother to actually calculate the return value of the expression <= . It does not matter that the expression always returns 0 or 1, because this value is never evaluated in fact.

The only time that relational operators that return 0 or 1 will matter is when their value is used in a larger expression, such as arithmetic or variable assignment. This is much less common than the situation when they directly use them in a branch, and the convenience of always returning 1 is not very expensive.

+1
source share

In C, 0 is false whether the return type is from a comparison operator or if statement or what you want to check. However, while the if () operator will accept something for a non-zero truth, the comparison operators should return only one object, and therefore it was decided that this object would be "1". This is the difference between whether you return or accept.

As in any other function, say int foo(int x){} , you can accept any value of x, but before you leave the function, you must choose what you want to return. I suppose you could return a random number, but what good would it do? Instead, "1" was selected.

0
source share

All Articles