98

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?

Kevin Dong
  • 5,001
  • 9
  • 29
  • 62
  • 3
    I guess this [SO Question](http://stackoverflow.com/questions/1608318/is-bool-a-native-c-type) is relevant – Imran Ali May 18 '16 at 06:25
  • 3
    I try to run this under `gcc` with `-std=c89` and it yields the same result. – Kevin Dong May 18 '16 at 06:27
  • Doesn't C usually use the all-caps `TRUE` and `FALSE` instead? I suppose it depends on the compiler, but I've always had to use all-caps versions in C. (Whereas C++, Java, C#, etc. have lower case `true` and `false`, but they also have built-in `bool`/`boolean` types, so that's another story.) – Darrel Hoffman May 18 '16 at 13:36
  • @DarrelHoffman: "Usually", yes. That is to say, Standard C does not define `TRUE`, C11 has `_True` and `true`, but many people had their own `#define TRUE (1)` back in C89. – MSalters May 18 '16 at 14:38
  • 1
    @Blackhole, from 15 to 0. – Arturo Torres Sánchez May 18 '16 at 14:53
  • 6
    Almost dupe but over a decade before SO/SE: http://c-faq.com/bool/bool2.html . – dave_thompson_085 May 18 '16 at 17:12
  • 1
    That false is zero is canon, however true is generally thought of as "not zero". Programmers being what they are however, we have all used 1 as "not zero" for our various reasons. You are encouraged not to trust a true to be exactly 1. While (0 == 0) is one in your example, something like (12 == 12) could just as easily have the value 12; also "true". – Engineer May 19 '16 at 04:44
  • Possible duplicate of [Is C/C++ bool type always guaranteed to be 0 or 1 when typecast'ed to int?](http://stackoverflow.com/questions/4276207/is-c-c-bool-type-always-guaranteed-to-be-0-or-1-when-typecasted-to-int) – GingerPlusPlus May 19 '16 at 05:41
  • Related http://stackoverflow.com/questions/1252134/strange-c-boolean-casting-behaviour-true-true – SztupY May 19 '16 at 10:58
  • 1
    @SiteNook: That is wrong. An expression of the form `x == y` is guaranteed to have value `0` or `1` if `x` and `y` are built-in types. – TonyK May 19 '16 at 14:17
  • Do the good old #DEFINE TRUE 0; :) – Jeff.Clark May 19 '16 at 16:24
  • The use of the royal "we" here makes it sound like the C language is something that existed in nature and was discovered by scientists, not something invented my man – Wayne May 24 '16 at 18:35
  • @TonyK - SiteNook's comment is true (false is zero, true is not zero), although the example used at the end may have incorrectly illustrated his point, which I take to be the result of an expression that is anything other than zero will also evaluate to true. – Rob Craig May 24 '16 at 19:12
  • @Rob: "something like (12 == 12) could just as easily have the value 12": try as I might, I can't interpret that in a way that makes it true. – TonyK May 24 '16 at 20:20
  • @TonyK: Agreed, which is why I said his example incorrectly illustrates the point I think he was trying to make with the rest of his comment. – Rob Craig May 26 '16 at 14:24

8 Answers8

110

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.

haccks
  • 104,019
  • 25
  • 176
  • 264
  • 22
    It seems to me that the question is about `0 == 0` and `0 != 0` etc., not the value of macros. – M.M May 18 '16 at 06:43
  • @M.M; I can see two questions there. – haccks May 18 '16 at 06:44
  • 9
    I think that when he wrote `true` he meant "the value of a true comparison" or something, not the macro `true` – M.M May 18 '16 at 06:45
  • 1
    @KevinDong; Yes, C99 draft has similar paragraph. – haccks May 18 '16 at 07:47
  • 1
    @haccks: you can say about it without hesitate "identical" I just pciked your quote up since I was too lazy to look up by paragraph since I refer to c99 when ever needed. And I was able to find it by just searching it via `ctrl`+`f` ;) – dhein May 18 '16 at 12:18
  • 1
    @Zaibis; Thanks. I don't have copy of C99, but I know it is mentioned in there. – haccks May 18 '16 at 12:35
  • "For any pair of operands, exactly one of the relations is true." wait, really? Even for `double`? I'm pretty sure that they can both return false in C++ when comparing two `NaN`s – Mooing Duck May 19 '16 at 16:41
  • 2
    @MooingDuck: `NaN == NaN` is false and `NaN != NaN` is true. There is no problem with that statement. – kennytm May 20 '16 at 15:41
57

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 …

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
23

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.

Community
  • 1
  • 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 2
    note that `||`, `==`, `!=` etc. yield `int`, not a boolean type – M.M May 18 '16 at 06:44
  • 2
    I vote this question for the correct one. For me the question is also about the relational operators and not the macros. – ckruczek May 18 '16 at 06:48
  • "In the test part of `if`, `while`, `for`, etc, "true" just means "non-zero"." This is the salient part of the answer and is, in my opinion, an unfortunate choice of Dennis Ritchie from long ago. Anyone who has written functions that return error codes as the return value generally have `#define noErr 0` and any non-zero error code is an error. And then the problem is the simplicity and beauty of `if ( ready_to_do_something() ){do_something();}` doesn't work. It has to be `if ( !not_ready_to_do_something() ){do_something();}` "There are many falsehoods, but only one truth." TRUE should be 0. – robert bristow-johnson May 18 '16 at 14:37
  • Out of curiosity, how did the first drafts of C rules specify the behavior of "&&" and "||" in the case where the operands had values other than 0 or 1? The text you quote says "logical expressions" connected by && and ||, but what if those operators connect things other than logical expressions? – supercat May 18 '16 at 17:00
  • @supercat, K&R states much the same as C89. K&R A17.4, for example: `The && operator ... returns 1 if both its operands compare unequal to zero, 0 otherwise)`. I'll add that to the answer. – paxdiablo May 19 '16 at 01:14
  • @robertbristow-johnson The problem is you confusing **error** code with **success** code, not Ritchie's choice. I had seen numerous similar situations with variables such as `isHidden` vs `isVisible` and it has nothing to do with the underlying type. And the verbose solution is `if(ready_to_do_something() == STATUS_READY)` anyway. In higher level languages you can define implicit casts to `bool` - but it doesn't mean that you should. – Agent_L May 19 '16 at 09:32
  • well, i still think that a language could be constructed so that if integers are used for `boolean` that the notion of *only one truth and many falsehoods* would appear congruent to *only one zero and many non-zeros*. then when logical statements are implemented, they are implemented with the value of TRUE to be 0 and the value of FALSE to be -1 (all bits set to one). but in testing, **anything** non-zero would be FALSE. i just think that could be done. and truth == success. – robert bristow-johnson May 19 '16 at 16:33
  • Do you know if the stipulation that the logical, relational and comparison operators yield 1 for true was in the first edition of K&R? My recollection is that it could not be relied on, but that may have just been a conservative generalization on my part. – sdenham May 19 '16 at 17:46
  • 1
    @sdenham, yes. In the *earliest* copy of K&R I have (first edition, print run 14, one so early that it mentions the hardware characteristics of four typical machines, the PDP-11, Honeywell-6000, IBM-370 and Interdata-8/32), `A.7.6/7/10/11` (relational/equality/logical-and/logical-or) all specify that it gives 0 or 1 as a result. Have updated answer to include that. – paxdiablo May 20 '16 at 01:19
12

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?

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 1
    `sizeof(bool)` is implementation specific in C++. See http://stackoverflow.com/questions/4897844/is-sizeofbool-defined . – David Hammen May 18 '16 at 09:59
  • @DavidHammen Just as sizeof(0 == 0) is implementation-defined too. It is just an example. – Lundin May 18 '16 at 10:44
  • I thought C did change the rules for Boolean types. Other kinds of uintN types (including many older compilers' "bit" types) store the lower N bits of a value and ignore any higher bits, while the new Boolean types effectively "or" together all the bits. – supercat May 18 '16 at 16:58
  • 1
    Should that be `if(ptr != NULL)`, or perhaps `if(!ptr)`? – Mathieu K. May 18 '16 at 18:20
  • 1
    `if(c == '\0')` lends itself to the particularly common beginners mistake of coding `if(c = '\0')`, so I avoid it. Agreed, `if(c)` is bad...it should be, for example, `if(valveIsOpen)` – aja May 19 '16 at 22:05
  • @aja = vs == is a dead horse argument, how to handle that bug was solved in the 80s. Any decent compiler can nowadays warn for assignment inside conditions, enable that warning, end of story. Don't let 1980s bugs affect how you write code in 2016. `if(something)` is regarded as good style if "something" is a boolean variable though. Essentially you should treat all conditions as if they were functions requiring a bool parameter. – Lundin May 20 '16 at 06:30
3

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.

Russell Hankins
  • 1,196
  • 9
  • 17
  • how can ! change all the 0's to 1's and still produce 0 for !5 ? – codeshot Sep 03 '19 at 20:26
  • @codeshot It can't. But the point he's making is that not all languages treat the operand of ! as a boolean. Some treat ! as C's ~ -- that is, a bitwise complement. In which case, determining the resulting value requires knowing the type of the variable in the first place, so !(uint32_t)5 would be 4,294,967,290. But !0 is still 4,294,967,295, and 4,294,967,295 is truthy. – Pegasus Epsilon Aug 28 '20 at 19:33
1

It happened because of the Relational Operators in your printf statement.

Operator == and operator !=

Since (0 == 0) holds true so, it gives a value 1

whereas, (0 != 0) doesn't hold true so, gives a value 0 .

SKD
  • 464
  • 1
  • 4
  • 16
1

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.

Tommy
  • 21
  • 1
0

I think I might have found the perfect solution to your problem. Yes, 0 and any non-zero number are False and True respectively. Though there is no boolean data type in C.

But this is not the problem, the actual problem is how you are dealing with the modification of variable a in the your code :

int a = 16;

while (a--){
    printf("%d\n", a);
}

When the compiler comes to the while (condition) statement, first the value of a is read by the compiler for the condition, then the arithmetic operation takes place, in this case,
a = a - 1 / a -= 1. So in the end there will be a case when a = 1 and the condition satisfies and after the arithmetic operation a-- which leads to a = 0, the print statement prints a as 0.

The above scenario depends on whether you use --a or a--. These two statements are read by the compiler in the order they are written. For --a first the operation is performed on a then its value is read and vice-versa for the other.

So for case --a when a = 1 first the operation is done i.e a = a - 1 / a -= 1 and then a is evaluated for the condition, which then comes out to be Falsy as a = 0. Try the code below :

int a = 16;

while (--a){
    printf("%d\n", a);   // prints numbers from 15 to 1 as intended
}

OR deal with the modification of a inside the while loop block.

int a = 16;

while(a){
    a = a - 1;           // or a -= 1
    printf("%d\n", a);   // also prints numbers from 15 to 1 as intended
}
Harshit Singh
  • 101
  • 1
  • 7
  • This may be somewhat interesting, but it's not relevant: OP clearly intended to print from 15 to 0 inclusively, and did not have a problem with that. They wanted to know about the nature of true and false in C, they did not have a problem with their code. – joanis Apr 09 '22 at 16:54
  • No that is what everyone got wrong, I'm also a beginner so could relate to him. He surely has thought that if 0 is falsy then why it's being printed in the loop coz when while (0) comes the loop should exit without reaching the print statement, but it printed. So this is what made him doubt if 0 is even false or not. – Harshit Singh Apr 09 '22 at 17:26
  • Well, OK, if that was the problem that caused you some trouble, maybe you're not going to be the only one. – joanis Apr 09 '22 at 17:29
  • 1
    See the comments of the OG question, Kevin is worried about the loop and print results, so he checked with another compiler – Harshit Singh Apr 09 '22 at 17:32