Do negative numbers return false in C/C++?
Solution 1
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.
Solution 2
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.
Solution 3
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
Solution 4
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.
Admin
Updated on July 08, 2022Comments
-
Admin almost 2 years
When evaluating integers as booleans in C/C++, are negative numbers true or false? Are they always true/false regardless of compilers?
-
rici over 10 yearsIn standard C (99 or 11, at least), LONG_MIN must be less than or equal to -2147483647, and decimal integer constants are given the first type of
int
,long int
,long long int
which can represent the number. Consequently,-65536
will be eitherint
orlong int
, and in any case negative. So regardless of the bitness of the machine,if (-65536) do_it();
will alwaysdo_it()
. Had you assigned-65536
(or, for that matter,65536
) touint16_t a
, thenif (a) do_it();
probably wouldn'tdo_it()
, buta
probably wouldn't be negative (UB, though). -
DanielV over 10 yearsOn a 16 bit microcontroller, int and long int are probably both going to be 16 bits, in which case -65536 will be stored as the literal zero, maybe with a compiler warning, but it will still be zero.
-
rici over 10 years@danielV: if long int is 16 bits, then what you have is not a compliant C compiler, and if the C compiler is not compliant,then it might do anything, but it's no longer C. A compliant compiler would have to provife software 32-bit arithmetic. It's not hard to do. gcc implements 64-bit arithmetic on machines with only 32 bit ALUs. The standard is very clear about the minimum size of long.
-
Shafik Yaghmour over 10 yearsBeing nit-picky but an example run on one or even several compilers does not prove this works or should work across all of them, i.e. that it is not implementation dependent.
-
Brendan Long over 10 years@ShafikYaghmour That's true. I updated the answer to give some more detail, and also add
-Wall -pedantic
, to show that gcc doesn't see anything wrong with this. I created this answer after the spec ones, mainly to show that the first part of the question is easily testable. -
phuclv almost 10 years@DanielV according to the standard long must be at least 32 bits
-
Keith Thompson over 4 yearsNote that the question (perhaps not entirely appropriately) asks about both C and C++. The result is the same in both, but the rules are stated differently. See my answer for the gory details.