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
trueandfalseas0and1respectively?
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
#ifpreprocessing directives. They aretruewhich expands to the integer constant
1,falsewhich 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 yields1if the specified relation is true and0if 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
_Boolis 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
#ifpreprocessing directives. They are —true— which expands to the integer constant 1, …§7.17.5.1/3: The
atomic_is_lock_freegeneric 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
iswctypefunction 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 > jand logical expressions connected by&&and||are defined to have value1if true, and0if 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