Can results of boolean operations be compared? - c

Does the C standard ensure that the boolean operations (==, !=, >, &&, ||, etc) always have the same value to represent truthfulness? In other words, do they always return some positive constant if true, or is the only guarantee that it will be a positive number?
The reason I'm asking this is to know if statements such as the one below are valid. That expression should be true if both pointers are NULL or both pointers point somewhere (not necessarily the same place).
if ((ptr1 == NULL) == (ptr2 == NULL))

Yes, although the rule for interpretation of integral values as boolean values by C states that 0 is false and any other value is true (a), the results of comparison operators is always 1 or 0.
So the expression (a == b) will never give you 42, for example.
The relevant bits of the standard (C11) are all under 6.5 Expressions:
6.5.8/6: Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false.
6.5.9/3: The == (equal to) and != (not equal to) operators are analogous to the relational operators except for their lower precedence. Each of the operators yields 1 if the specified relation is true and 0 if it is false.
6.5.13/3: The && operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it yields 0.
6.5.14/3: The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it yields 0.
That covers all the ones you explicitly mentioned in your question. The only other boolean operation I can think of (off the top of my head) is the logical NOT operator ! which is also covered:
6.5.3.3/5: The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0.
(a): See C11 sections dealing with if, while, do and for, which all contain language along the lines of something happen if/while "the expression compares unequal to zero". Specifically:
6.8.4.1/2: In both forms [of the if statement, one with and one without an else clause], the first substatement is executed if the expression compares unequal to 0. In the else form, the second substatement is executed if the expression compares equal to 0.
6.8.5/4: An iteration statement [while, do and for] causes a statement called the loop body to be executed repeatedly until the controlling expression compares equal to 0.

Yes.
Values generated by operators will always be 1 for true and 0 for false.

The results of
negation operator (!)
relational operators (<, >, <=, >=)
equality operators (==, !=)
logical operators (&&,  ||)
is an int value of either 0 (false) or 1 (true).

Related

C by K&R - numeric value of a relational or logical expression

In section 2.6 "Relational and Logical Operators" on page 42 in "The C Programming Language" 2nd by K&R, the authors said:
By definition, the numeric value of a relational or logical expression
is 1 if the relation is true, and 0 if the relation is false.
I'm confused by that wording. For example, in the logical expression
x && y
there is no relation which can be true or false. Isn't the wording supposed to be:
By definition, the numeric value of a relational or logical expression
is 1 if the expression is true, and 0 if the expression is false.
x && y
Since x and y are being used in conjuntion with && the compiler needs logical (boolean)values
In c 0 is false and not 0 is true. Hence the statement you posted from the standard that a logical expression evaluates to 0 or not zero (in fact 1, but in testing any non zero value is treated as true).
Thus this code is interpreted as
(x != 0) && (y != 0)
the depending of the current values of x and y this becomes, say
1 && 0
THis is
true && false
by the rule that 0 == false and !0 == true. This expression is thus false, and therefore evaluates to 0 by the statment you posted.
Note that much of this confusion comes form the fact the c originally had no boolean type. Hence the convention that 0 = false and !0 = true. This has the beneficial side effect of allowing numbers and in particular pointers to be tested directly as in
while(ptr--)
{
}
Which is equivalent to
while(ptr-- != 0)
{
}
A relational or logical expression is the result of an operator such as &&, ||, ==, '>=,<=, etc. In this context,x && y` is a logical expression which will evaluate to either 0 or 1.
The arguments to && need not be logical expressions. When evaluated in a boolean context, a numeric value of 0 evaluates to false while a non-zero value evaluates to true. So in the case of x && y the expression will evaluate to 1 (i.e. true) if both x and y are non-zero.
This is not relational operator.(You shouldn't take the word relation on that context also). This is logical AND. The wording is correct.
Here each of the variable's value x and y if non zero will evaluate to truthy value. And if both of them are true then it will be true - the whole expression would be true.
And here by relation it means the relation of each subexpression being truthy or not which in turn decides whether whole expression is true or false. In your case the relation is simply whether x is nonzero or not AND y is nonzero or not.
The wording is correct. Relation is a mathematical term.
Every operator in C returning a boolean can be considered a relation.

Return value of a boolean expression in C

For reasons that are not worth mentioning, I want to know if there's a standard defined value for boolean expressions. E.g.
int foo () {
return (bar > 5);
}
The context is that I'm concerned that our team defined TRUE as something different than 1, and I'm concerned that someone may do:
if (foo() == TRUE) { /* do stuff */ }
I know that the best option would be to simply do
if (foo())
but you never know.
Is there a defined standard value for boolean expressions or is it up to the compiler? If there is, is the standard value something included in C99? what about C89?
An operator such as ==, !=, &&, and || that results in a boolean value will evaluate to 1 of the expression is true and 0 if the expression is false. The type of this expressing is int.
So if the TRUE macro is not defined as 1, a comparison such as the above will fail.
When an expression is evaluated in a boolean context, 0 evaluates to false and non-zero evaluates to true. So to be safe, TRUE should be defined as:
#define TRUE (!0)
As was mentioned in the comments, if your compiler is C99 compliant, you can #include <stdbool.h> and use true and false.
According to C99:
6.5.3.3 (Unary arithmetic operators)
The result of the logical negation operator ! is 0 if the
value of its operand compares unequal to 0, 1 if the value of its
operand compares equal to 0. The result has type int. The
expression !E is equivalent to (0==E).
6.5.8 (Relational operators)
Each of the operators < (less than), > (greater than), <=
(less than or equal to), and >= (greater than or equal to)
shall yield 1 if the specified relation is true and 0 if it is false.
The result has type int.
6.5.9 (Equality operators)
The == (equal to) and != (not equal to) operators are
analogous to the relational operators except for their lower
precedence. Each of the operators yields 1 if the specified
relation is true and 0 if it is false. The result has type
int.
6.5.13 (Logical AND operator)
The && operator shall yield 1 if both of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
6.5.14 (Logical OR operator)
The || operator shall yield 1 if either of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
The C programming language does not define Boolean value. Traditionally, the C programming language uses integer types to represent boolean data types.
Boolean values in C:
0 = false`
Any other value = true`
Usually people will use 1 for true.
C99 introduced the_Bool data type that is not available in other C derivates.See wikipedia link here. Additionally, a new header stdbool.h has been added for compatibility reasons. This header allows programmers to use boolean types in the same way, as in C++ language.
To use bool in C, we can use enum as below.
enum bool {
false, true
};
bool value;
value = bool(0); // False
value = bool(1); // True
if(value == false)
printf("Value is false");
else
printf("Value is true");
Also, related Stack overflow question
Is bool a native C type?

Expressions in c return 1 for true

In c programming ,all non zero numbers can be used in conditional expressions to return true. In that aspect why do expressions which evaluate to true return 1 ,not any other non zero value?
#include<stdio.h>
int main()
{
printf("%d",6==6);
}
output: 1
This is defined in the C standard:
6.5.13 Logical AND operator
The && operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it yields 0. The result has type int.
Similar for the other logical operators.
It makes a lot of sense to have a deterministic value for these cases, and the lowest positive non-zero value is a good candidate for that.
C11 draft
6.5.9 Equality operators
3
The == (equal to) and != (not equal to) operators are analogous to the
relational operators except for their lower precedence.108) Each of
the operators yields 1 if the specified relation is true and 0 if it
is false. The result has type int. For any pair of operands, exactly
one of the relations is true.
Because as you said, evaluating the both sides of that kind of expressions, the result could be true or false, that is a boolean value. By definition and convetion, in C standard, boolean values are represented with a 1 for true and 0 for false.

Any C compiler where "==" evaluates to larger than one?

As anything non-zero means true, but the >, <, == etc. operators returning 1 for true, I'm curious if there are any notable C compilers where these operators can result in a value greater than 1.
In other words, is there any compiler where int i = (a==b); would result in undefined behavior if I intended to use i not as a boolean value, but as an integer, and was assuming it would be either 0 or 1 ?
No, if there are, they're not C compilers :-) The standard mandates that relational and equality operators return 1 for true and 0 for false.
The rule for interpretation of integral values as boolean values by C states that 0 is false and any other value is true. See C11 sections dealing with if/while/do/for, which all contain language like "while the expression compares unequal to zero". Specifically:
6.8.4.1/2: In both forms [of the if statement, one with and one without an else clause], the first substatement is executed if the expression compares unequal to 0. In the else form, the second substatement is executed if the expression compares equal to 0.
6.8.5/4: An iteration statement [while, do and for] causes a statement called the loop body to be executed repeatedly until the controlling expression compares equal to 0.
However, it's quite explicit what result you will get for the comparison-type expressions, you either get 0 or 1. The relevant bits of the C11 standard for these are all under 6.5 Expressions:
6.5.8/6: Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false.
6.5.9/3: The == (equal to) and != (not equal to) operators are analogous to the relational operators except for their lower precedence. Each of the operators yields 1 if the specified relation is true and 0 if it is false.
6.5.13/3: The && operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it yields 0.
6.5.14/3: The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it yields 0.
6.5.3.3/5: The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0.
And this behaviour goes way back to C99 and C89 (ANSI days). The C99 sections dealing with relational and equality operators also states that the return values is either 0 or 1.
And, while the C89 draft doesn't explicitly dictate the return values for equality operators, it does say:
The == (equal to) and the != (not equal to) operators are analogous to the relational operators except for their lower precedence.
And the relational operators section does state:
Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false.
Reference: http://flash-gordon.me.uk/ansi.c.txt since I don't have any copies of the C89 standards floating around. I do have the second edition of K&R (the ANSI one from 1988) which basically says the same thing, in sections A7.9 and A7.10 of Appendix A, the Reference Manual. If you want a definitive answer from the first edition, that'll have to come from someone with a wife less prone to throwing out old junk.
Addendum:
According to Michael Burr, who is either not married or has a more accommodating wife than I in terms of keeping old books :-)
K&R 1st Edition (1978) also says the same in 7.6 and 7.7: "The [relational operators] all yield 0 if the specified relation is false and 1 if it is true." ... "The [equality operators] are exactly analogous to the relational operators except for their lower precedence."
They are guaranteed to return 0 or 1.
Reference:
C99 Standard: 6.5.9 Equality operators
Para 3:
The == (equal to) and != (not equal to) operators are analogous to the relational
operators except for their lower precedence.108) Each of the operators yields 1 if the
specified relation is true and 0 if it is false. The result has type int. For any pair of
operands, exactly one of the relations is true.
I don't think people here are answering the question. Question was not about what the standard says, the question was about if there are any notable compilers out there that do not obey the standard in that regard.
No, as far as I know, there are not.
I don't have access to the C standard, but according to Wikipedia:
C uses an integer type, where relational expressions like i > j and logical expressions connected by && and || are defined to have value 1 if true and 0 if false, whereas the test parts of if, while, for, etc., treat any non-zero value as true.
Wikipedia luckily does have the correct citations, but as they're references to books, not sure how much help that is :).
As far as i can find is this from 6.5.9 paragraph 3 in C99 standard
The == (equal to) and != (not equal to) operators are analogous to the
relational operators except for their lower precedence.108) Each of
the operators yields 1 if the specified relation is true and 0 if it
is false. The result has type int. For any pair of operands, exactly
one of the relations is true.
Therefore it seems that the evaluated values should be either 1 or 0
By specification, to be considered the C language, the conditional operators must return 0 for false and 1 for true.
In haiku form:
Specification
Disallows this behavior,
Otherwise not C.
Before c89/c90/ANSI-C, the compare operators were guaranteed to produce a zero value on a "false" condition, and not-equal-to-zero otherwise. The substitute 1 for true "standardisation" that was introduced by c89 is seldomly needed, and in cases where is is needed, one could use a = (b==c) ? 1 : 0;.

Is the "true" result of >, <, !, &&, || or == defined?

When I for instance write 7>1 in C (say C99 if this is not an always-been feature), can I expect the result will be exactly 1 or just some non-zero value? Does this hold for all bool operators?
In C99 §6.5.8 Relational Operators, item 6 (<,>,<= and >=):
Each of the operators < (less than), > (greater than), <= (less than or equal to), and >=
(greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false)
The result has type int.
As for equality operators, it's a bit further in §6.5.9 (== and !=):
The == (equal to) and != (not equal to) operators are analogous to the relational
operators except for their lower precedence) Each of the operators yields 1 if the
specified relation is true and 0 if it is false. The result has type int. For any pair of
operands, exactly one of the relations is true.
The logical AND and logical OR are yet a bit further in §6.5.13 (&&)
The && operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it
yields 0. The result has type int.
... and §6.5.14 (||)
The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it
yields 0. The result has type int.
And the semantics of the unary arithmetic operator ! are over at §6.5.3.3/4:
The result of the logical negation operator ! is 0 if the value of its operand compares
unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int.
The expression !E is equivalent to (0==E).
Result type is int across the board, with 0 and 1 as possible values. (Unless I missed some.)
C follows Postel's Law for its boolean operators: be conservative in what you do, be liberal in what you accept from others. It will treat any non-zero value as true in boolean expressions, but it will always produce either a 0 or a 1 itself. 2 != 3 is always 1.
From the ISO C99 standard, section 6.5.8:
6 Each of the operators < (less than), > (greater than), <= (less than
or equal to), and >= (greater than or equal to) shall yield 1 if the
specified relation is true and 0 if it is false. The result has
type int.
From section 6.5.9:
3 The == (equal to) and != (not equal to) operators are analogous to
the relational operators except for their lower precedence. Each
of the operators yields 1 if the specified relation is true and 0 if
it is false. The result has type int. For any pair of operands,
exactly one of the relations is true.
Same thing happens with the logical conjunction (&&) and disjunction (||) operators.
PS: Incidentally, this is why the bitwise operators (& and |) can usually be used as non-short-circuiting versions of the logical operators.
All C operators that yield logically true/false values always yield a result of type int with the value 0 for false, 1 for true.
That's not the case for all C expressions that yield logically true/false values. For example, the is*() character classification functions declared in <ctype.h> (isdigit(), isupper(), etc.) return 0 if the condition is false, but may return any non-zero value if the condition is true.
As long as you use the result directly as a condition:
if (isdigit(c)) ...
if (!isdigit(c)) ...
if (isdigit(c) || islower(c)) ...
and don't attempt to compare it to something:
if (isdigit(c) == 1) ... /* WRONG */
if (isdigit(c) == true) ... /* ALSO WRONG */
this shouldn't cause any problems.
(You can safely compare the result to 0 or false, but there's no good reason to do so; that's what the ! operator is for.)

Resources