Do negative numbers return false in C/C++?
All non-zero values will be converted to true
, and zero values to false
. With negative numbers being non-zero, they are converted to true
.
Quoting from the C++11 standard (emphasis mine):
4.12 Boolean conversions [conv.bool]
1 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to
false
; any other value is converted totrue
. A prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.
Are they always true/false regardless of compilers?
You will only get the above guarantee when your compiler is standards-compliant, or at least, complies with this specific part of the standard. In practice, all compilers have this standard behavior, so there isn't much to worry about.
Short answer: Negative values, and any non-zero values in general, are treated as true when used as conditions.
For C, there are a number of contexts in which an expression is treated as a condition. Conditions are not necessarily of type bool
or _Bool
; that type was only added to the language by the 1999 standard.
The most obvious of these contexts is the expression in an if
statement, but there are other examples: while
, do-while
, the second expression in a for
header, the first operand of the ?:
conditional operator, and the operand(s) of the !
, &&
, and ||
operators. (I think that's an exhaustive list, but I'm not certain.)
Here's what the C standard says about the behavior of the if
statement (the "two forms" refer to if
with and without an else
clause):
In both forms, the first substatement is executed if the expression compares unequal to 0.
Which means that this:
if (foo) ...
is equivalent to this:
if ((foo) != 0) ...
(adding extra parentheses to avoid any operator precedence issues). The meaning is clear if foo
is of type int
. If foo
is of some floating-point type, 0
is converted to the same type (which can cause some subtleties if the value happens to be a negative zero or a NaN). And if foo
is a pointer, 0
is treated as a null pointer constant; if (ptr)
is equivalent to if (ptr != NULL)
(assuming the definition of NULL
is visible).
For C++, the rules are stated a bit differently, but the effect is the same. The condition in a C++ if
statement is converted to type bool
(unlike in C, the type bool
has been built into C++ since its early history). The conversion of a value of any scalar type to bool
is defined by the C++ standard as:
A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. A prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.
So in both C and C++, any scalar (i.e., integer, floating-point, or pointer) value can be used as a condition, and the condition is false if the scalar is equal to zero, and true if it's not equal to zero. C defines this as an inequality comparison to 0
; C++ defines it as a conversion to the bool
-- but the result is the same.
This is getting a bit off the topic of the question, but I'll mention that it's important to note that a value that is treated as a true condition is not necessarily equal to true
. true
(which is 1
in C if you have #include <stdbool.h>
, and a unique value of type bool
in C++) is just one of many values that possess "truthiness" when used in a condition. Which is why you should almost never write:
if (cond == true) ...
in either C or C++ (unless you really need to compare it to that one value); just write:
if (cond) ...
A C++ example:
#include <iostream>
int main() {
int n = 2;
if (n) std::cout << "n has truthiness\n";
else std::cout << "n does not have truthiness\n";
if (n == true) std::cout << "n == true\n";
else std::cout << "n != true\n";
}
The output is:
n has truthiness
n != true
You can test it yourself by compiling this:
#include <stdio.h>
int main(int argc, char** argv) {
if (-1) {
printf("-1 is true\n");
} else {
printf("-1 is false\n");
}
return 0;
}
Results:
$ gcc -Wall -pedantic test.c -o test-c
$ g++ -Wall -pedantic test.c -o test-cpp
$ ./test-c
-1 is true
$ ./test-cpp
-1 is true
Of course, to answer the second part of your question, "Are they always true/false regardless of compilers?", the only way to be completely sure is to look at the spec. In general though, compilers will warn you if you do something dangerous, and you can see from the output above, that even with "pedantic" warnings, gcc
considers this code to be perfectly fine.