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 to true. 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.

Tags:

C++

C

Boolean