Jason Maldonado
Jason Maldonado

Reputation: 842

Do negative numbers return false in C/C++?

When evaluating integers as booleans in C/C++, are negative numbers true or false? Are they always true/false regardless of compilers?

Upvotes: 66

Views: 86061

Answers (5)

Keith Thompson
Keith Thompson

Reputation: 263227

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 ("both forms" refers 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 bool -- but the result is the same.

This is getting a bit off the topic of the question, but 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

(C also has built-in complex types. A complex value is treated as true unless both its real and imaginary parts are equal to zero.)

(The upcoming 2023 edition of the C standard will have bool as a built-in type, and false and true as keywords.)

Upvotes: 8

Brendan Long
Brendan Long

Reputation: 54242

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.

Upvotes: 9

Shafik Yaghmour
Shafik Yaghmour

Reputation: 158459

Anything that is not 0 will be converted to true(1 in the case of C) a zero value will be converted to false(0 in the case of C). With respect to C if we look at the C99 draft standard section 6.3.1.2 Boolean type paragraph 1 says:

When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1.

For completeness sake if we look at section 7.16 Boolean type and values paragraph 2 says:

The macro 

 bool

expands to _Bool.

with respect to C++ the draft C++ standard in section 4.12 Boolean conversions paragraph 1 says(emphasis mine):

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.[...]

This should hold regardless of which compiler you use.

Upvotes: 3

DanielV
DanielV

Reputation: 663

Good question. The answer is "depends".

if (-1) { // this is always true
}

On the other hand, suppose you are on a 16 bit machine:

if (-65536) { // this is always false
}

On the other hand,

int a = whatever doesn't matter;
if (a < 0) { // this might or might not be true
    if (a) { // this will always be true if we get here
    }
}

So negative numbers are not always false, except sometimes they always are.

Upvotes: -3

Mark Garcia
Mark Garcia

Reputation: 17708

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.

Upvotes: 88

Related Questions