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?
C does not have boolean data types, and normally uses integers for boolean testing. Zero is used to represent false, and One is used to represent true. For interpretation, Zero is interpreted as false and anything non-zero is interpreted as true.
Boolean values and operations C++ is different from Java in that type bool is actually equivalent to type int. Constant true is 1 and constant false is 0. It is considered good practice, though, to write true and false in your program for boolean values rather than 1 and 0.
Hence, if (! (-1)) will evaluate to FALSE. Detail: "In standard C, any non-zero (positive/negative) value is TRUE." --> close.
For this, C++ has a bool data type, which can take the values true (1) or false (0).
Does the C standard explicitly indicate the truth values of
true
andfalse
as0
and1
respectively?
The C standard defines true
and false
as macros in stdbool.h
which expand to 1
and 0
respectively.
C11-§7.18:
The remaining three macros are suitable for use in
#if
preprocessing directives. They aretrue
which expands to the integer constant
1
,false
which expands to the integer constant
0
[...]
For the operators ==
and !=
, standard says
C11-§6.5.9/3:
The
==
(equal to) and!=
(not equal to) operators are analogous to the relational operators except for their lower precedence.108) Each of the operators yields1
if the specified relation is true and0
if it is false. The result has typeint
. For any pair of operands, exactly one of the relations is true.
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 macro true
expands to 1
(§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).
§6.2.5/2: An object declared as type
_Bool
is large enough to store the values 0 and 1.§6.5.5.3/5: The result of the logical negation operator
!
is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. …§6.5.8/6: Each of the operators
<
(less than),>
(greater than),<=
(less than or equal to), and>=
(greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false.107) …§6.5.9/3: The
==
(equal to) and!=
(not equal to) operators are analogous to the relational operators except for their lower precedence.108) Each of the operators yields 1 if the specified relation is true and 0 if it is false. …§6.5.13/3: The
&&
operator shall yield 1 if both of its operands compare unequal to 0; …§6.5.14/3: The
||
operator shall yield 1 if either of its operands compare unequal to 0; …§6.10.1/1: … it may contain unary operator expressions of the form —
defined identifier
— or —defined ( identifier )
— which evaluate to 1 if …§7.4.1 (Character classification functions)/1: The functions in this subclause return nonzero (true) if and only if …
§7.18/3: The remaining three macros are suitable for use in
#if
preprocessing directives. They are —true
— which expands to the integer constant 1, …§7.17.5.1/3: The
atomic_is_lock_free
generic function returns nonzero (true) if and only if the object’s operations are lock-free. …§7.30.2.1 (Wide character classification functions)/1: The functions in this subclause return nonzero (true) if and only if …
§7.30.2.2.1/4: The
iswctype
function returns nonzero (true) if and only if …
There are two areas of the standard you need to be aware with when dealing with Boolean values (by which I mean true/false values rather than the specific C bool/_Bool
type) in C.
The first has to do with the result of expressions and can be found in various portions of C11 6.5 Expressions
(relational and equality operators, for example) . The bottom line is that, whenever a Boolean value is generated by an expression, it ...
... yields 1 if the specified relation is true and 0 if it is false. The result has type int.
So, yes, the result of any Boolean-generating expression will be one for true, or zero for false. This matches what you will find in stdbool.h
where the standard macros true
and false
are defined the same way.
Keep in mind however that, following the robustness principle of "be conservative in what you send, liberal in what you accept", the interpretation of integers in the Boolean context is somewhat more relaxed.
Again, from various parts of 6.5
, you'll see language like:
The
||
operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it yields 0. The result has type int.
From that (and other parts), it's obvious that zero is considered false and any other value is true.
As an aside, the language specifying what value are used for Boolean generation and interpretation also appear back in C99 and C89 so they've been around for quite some time. Even K&R (ANSI-C second edition and the first edition) specified that, with text segments such as:
Relational expressions like
i > j
and logical expressions connected by&&
and||
are defined to have value1
if true, and0
if false.In the test part of
if
,while
,for
, etc, "true" just means "non-zero".The
&&
operator ... returns 1 if both its operands compare unequal to zero, 0 otherwise.The
||
operator ... returns 1 if either its operands compare unequal to zero, and 0 otherwise.
The macros in stdbool.h
appear back in C99 as well, but not in C89 or K&R since that header file did not exist at that point.
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:
In both forms, the first substatement is executed if the expression compares unequal to 0.
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:
Each of the operators yields 1 if the specified relation is true and 0 if it is false
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 header stdbool.h
defines macros bool
, true
and false
, that expand to _Bool
, 1
and 0
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 of if(ptr)
.
if((data & mask) != 0)
instead of if(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
if(c == '\0')
Good, the intent is clear, the code is self-documenting.
versus
if(c)
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With