We know that any numbers that are not equal to 0
are viewed as true
in C, so we can write:
int a = 16;
while (a--)
printf("%d\n", a); // prints numbers from 15 to 0
However, I was wondering whether true / false are defined as 1
/0
in C, so I tried the code below:
printf("True = %d, False = %d\n", (0 == 0), (0 != 0)); // prints: True = 1, False = 0
Does C standard explicitly indicate the truth values of true and false as 1
and 0
respectively?
You are mixing up a lot of different things: control statements, operators and boolean types. Each have their own rules.
Control statements work like for example the
if
statement, C11 6.4.8.1:while
,for
etc have the same rule. This has nothing to do with "true" or "false".As for operators that are supposedly yielding a boolean result, they are actually yielding an
int
with value 1 or 0. For example the equality operators, C11 6.5.9:All of the above is because C did not have a boolean type until the year 1999, and even when it did get one, the above rules weren't changed. So unlike most other programming languages where statements and operators yield a boolean type (like C++ and Java), they just yield an
int
, with a value zero or not zero. For example,sizeof(1==1)
will give 4 in C but 1 in C++.The actual boolean type in C is named
_Bool
and requires a modern compiler. The headerstdbool.h
defines macrosbool
,true
andfalse
, that expand to_Bool
,1
and0
respectively (for compatibility with C++).It is however considered good programming practice to treat control statements and operators as if they actually required/yielded a boolean type. Certain coding standards like MISRA-C recommend such practice. That is:
if(ptr == NULL)
instead ofif(ptr)
.if((data & mask) != 0)
instead ofif(data & mask)
.The aim of such style is to increase type safety with the aid of static analysis tools, which in turn reduces bugs. Arguably, this style is only meaningful if you do use static analysers. Though in some cases it leads to more readable, self-documenting code, for example
Good, the intent is clear, the code is self-documenting.
versus
Bad. Could mean anything, and we have to go look for the type of
c
to understand the code. Is it an integer, a pointer or a character?This answer needs to be looked at a bit more closely.
The actual definition in C++ is that anything not 0 is treated as true. Why is this relevant? Because C++ doesn't know what an integer is by how we think about it--we create that meaning, all it holds is the shell and rules for what that means. It knows what bits are though, that which make up an integer.
1 as an integer is loosely represented in bits, say an 8-bit signed int as 0000 0001. Many times what we see visually is a bit of a lie, -1 is a much more common way to represent it because of the signed nature of 'integer'. 1 really can't mean true proper, why? Because it's NOT operation is 1111 1110. That's a really major issue for a boolean. When we talk about a boolean, it's just 1 bit--it's really simple, 0 is false and 1 is true. All the logic operations hold as trivial. This is why '-1' should be designated as 'true' for integers (signed). 1111 1111 NOT'ed becomes 0000 0000---the logic holds and we're good. Unsigned ints is a little bit tricky and were a lot more commonly used in the past--where 1 means true because it's easy to imply the logic that 'anything not 0 is true'.
That's the explanation. I say the accepted answer here is wrong--there is no clear definition in the C/C++ definition. A boolean is a boolean, you can treat an integer as a boolean, but the fact the output is an integer says nothing about the operation actually being done is bitwise.
The C standard defines
true
andfalse
as macros instdbool.h
which expand to1
and0
respectively.C11-§7.18:
Regarding the operators
==
and!=
C11-§6.5.9/3:
It happened because of the Relational Operators in your
printf
statement.Operator
==
and operator!=
Since
(0 == 0)
holds true so, it gives a value1
whereas,
(0 != 0)
doesn't hold true so, gives a value0
.I've programmed in many languages. I've seen true be 1 or -1 depending on the language. The logic behind true being 1 was that a bit was either a 0 or 1. The logic behind true being -1 was that the ! operator was a one's complement. It changed all the 1's to 0's and all the 0's to 1's in an int. So, for an int, !0 = -1 and !(-1) = 0. This has tripped me up enough that I don't compare something to be == true, but instead compare it to be != false. That way, my programming style works in every language. So my answer is to not worry about it, but program so that your code works correctly either way.
It is not explicitly indicated in C11. All language-level operations will return 1 as truthy (and accept any nonzero including NaN as true).
_Bool
, then true must be 1 because the standard only require it to hold 0 and 1. (§6.2.5/2).<stdbool.h>
the macrotrue
expands to1
(§7.18/3)==
,!=
,<
,>
,<=
and>=
return 0 or 1 (§6.5.8/6, §6.5.9/3).!
,&&
and||
return 0 or 1 (§6.5.3.3/5, §6.5.13/3, §6.5.14/3)defined
expands to 0 or 1 (§6.10.1/1)But all standard library functions e.g.
islower
just say "nonzero" for truthy (e.g. §7.4.1/1, §7.17.5.1/3, §7.30.2.1/1, §7.30.2.2.1/4).