Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the C standard explicitly indicate truth value as 0 or 1?

Tags:

c

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?

like image 800
Kevin Dong Avatar asked May 18 '16 06:05

Kevin Dong


People also ask

Is 0 or 1 true or false in C?

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.

Is bool always 0 or 1?

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.

Does IF !(- 1 evaluate to true or false in C?

Hence, if (! (-1)) will evaluate to FALSE. Detail: "In standard C, any non-zero (positive/negative) value is TRUE." --> close.

Is 0 true or false in CPP?

For this, C++ has a bool data type, which can take the values true (1) or false (0).


4 Answers

Does the C standard explicitly indicate the truth values of true and false as 0 and 1 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 are

true

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 yields 1 if the specified relation is true and 0 if it is false. The result has type int. For any pair of operands, exactly one of the relations is true.

like image 149
haccks Avatar answered Oct 17 '22 16:10

haccks


It is not explicitly indicated in C11. All language-level operations will return 1 as truthy (and accept any nonzero including NaN as true).

  • If you concern about _Bool, then true must be 1 because the standard only require it to hold 0 and 1. (§6.2.5/2).
  • Also in <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 …

like image 31
kennytm Avatar answered Oct 17 '22 18:10

kennytm


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 value 1 if true, and 0 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.

like image 23
paxdiablo Avatar answered Oct 17 '22 16:10

paxdiablo


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?

like image 11
Lundin Avatar answered Oct 17 '22 18:10

Lundin