C doesn't have any built-in Boolean types. What's the best way to use them in C?
-
90C does have boolean type. At least there is one in the most recent standards. – Khaled Alshaya Dec 17 '09 at 12:50
-
12http://stackoverflow.com/questions/1608318/is-bool-a-native-c-type/1608350#1608350 – AnT stands with Russia Dec 17 '09 at 18:50
18 Answers
From best to worse:
Option 1 (C99 and newer)
#include <stdbool.h>
Option 2
typedef enum { false, true } bool;
Option 3
typedef int bool;
enum { false, true };
Option 4
typedef int bool;
#define true 1
#define false 0
Explanation
- Option 1 will work only if you use C99 (or newer) and it's the "standard way" to do it. Choose this if possible.
- Options 2, 3 and 4 will have in practice the same identical behavior. #2 and #3 don't use #defines though, which in my opinion is better.
If you are undecided, go with #1!

- 44,018
- 30
- 122
- 156
-
17
-
6@endolith The alignment, optimizations and way to store a `
` `bool` the compiler chooses may be more suitable for the intended purpose of a boolean value than utilizing an `int` (i.e. the compiler may choose to implement a `bool` differently than an `int`). It might also result in stricter type checking at compile time, if you're lucky. – blubberdiblub Mar 06 '20 at 06:16 -
5Why use `int` for `bool`? That's wasteful. Use `unsigned char`. Or use C's builtin `_Bool`. – May 19 '20 at 21:30
-
8@NoBody Using a smaller type can save on memory, but it might not make it any faster. Often, it's faster to use the processor's native word size instead of a smaller size as it could require the compiler to make bit shifts to align it properly – Ted Klein Bergman Jun 01 '20 at 06:22
-
6Options 2-4 do not behave the same as `
`. For example, they don't satisfy `(bool)(13 & 8) == true`. With options 2-4, you'd have to write `!!(13 & 8) == true` instead. This comes up all the time in bit-field testing... think of a macro that returns `(13 & 8)` with return type `bool`. – personal_cloud Aug 03 '20 at 03:58 -
-
1Also, `_Bool x = 0.5; printf("%d", x);` will output `1` while `int x = 0.5; printf("%d", x);` will output 0 instead. – tsh Feb 03 '23 at 02:43
A few thoughts on booleans in C:
I'm old enough that I just use plain int
s as my boolean type without any typedefs or special defines or enums for true/false values. If you follow my suggestion below on never comparing against boolean constants, then you only need to use 0/1 to initialize the flags anyway. However, such an approach may be deemed too reactionary in these modern times. In that case, one should definitely use <stdbool.h>
since it at least has the benefit of being standardized.
Whatever the boolean constants are called, use them only for initialization. Never ever write something like
if (ready == TRUE) ...
while (empty == FALSE) ...
These can always be replaced by the clearer
if (ready) ...
while (!empty) ...
Note that these can actually reasonably and understandably be read out loud.
Give your boolean variables positive names, ie full
instead of notfull
. The latter leads to code that is difficult to read easily. Compare
if (full) ...
if (!full) ...
with
if (!notfull) ...
if (notfull) ...
Both of the former pair read naturally, while !notfull
is awkward to read even as it is, and becomes much worse in more complex boolean expressions.
Boolean arguments should generally be avoided. Consider a function defined like this
void foo(bool option) { ... }
Within the body of the function, it is very clear what the argument means since it has a convenient, and hopefully meaningful, name. But, the call sites look like
foo(TRUE);
foo(FALSE):
Here, it's essentially impossible to tell what the parameter meant without always looking at the function definition or declaration, and it gets much worse as soon if you add even more boolean parameters. I suggest either
typedef enum { OPT_ON, OPT_OFF } foo_option;
void foo(foo_option option);
or
#define OPT_ON true
#define OPT_OFF false
void foo(bool option) { ... }
In either case, the call site now looks like
foo(OPT_ON);
foo(OPT_OFF);
which the reader has at least a chance of understanding without dredging up the definition of foo
.

- 319
- 2
- 13

- 16,074
- 4
- 30
- 37
-
1And how do you compare two variables for equality? Never using boolean constants works great, but it doesn't solve the problem when comparing against a non-constant. – Baruch Apr 28 '14 at 08:15
-
2Forgive me, but I don't understand the question. Are you asking how I compare two boolean variables for equality? If so, doesn't `a == b` work? – Dale Hagglund Apr 28 '14 at 09:44
-
It doesn't work because 'a' might have a value of 3, which is true, and 'b' might have a value of 5, which is true. But a == b should be true as well, which it isn't if they're ints. – Kenji Jun 28 '15 at 18:00
-
6@Kenji What you say is true, although I believe that using values other than one as equivalent for true is almost always a bad idea. So in your example, assuming that `a` and `b` count up from zero, I'd recommend `a > 0 == b > 0` instead. If you insist on taking advantage of the truthiness of arbitrary non-zero values, `!!var` yields the boolean 0/1 value equivalent to `var`, so you could write `!!a == !!b`, although quite a few readers will find it confusing. – Dale Hagglund Jun 29 '15 at 00:18
-
5`!a == !b` is also sufficient for testing equality, non-zeros become zero, and zeros become one. – ryanpattison Jul 10 '15 at 14:30
-
7@rpattiso You're quite right, of course, but I guess I would read `!!a` as "convert non-boolean a to its equivalent truth value", whereas I'd read `!a` as "logically invert the boolean variable a". In particular, I'd look for some specific reason the logical inversion was desired. – Dale Hagglund Jul 11 '15 at 23:23
-
1I would prefer writing some function `bool_equivalent(bool a, bool b)` wherever a comparison of boolean values must be done, since then the intent is clear. Of course, such a function could/should be implemented as `!a == !b` or `!!a == !!b`, whichever you prefer. – Jeremy West Jul 11 '17 at 01:34
-
1"Note that these can actually reasonably and understandably be read out loud." This might be the most useful advice in any StackOverflow answer I've read to date. Readability of code is a serious problem in general. – Bash May 20 '21 at 03:50
-
1@SebastianGaweda Thanks, I agree with you completely, and that belief goes well beyond boolean variables. Literal, out loud readability of code is an absolutely key indicator. I sometimes call it the "telephone test". – Dale Hagglund May 20 '21 at 04:26
A boolean in C is an integer: zero for false and non-zero for true.
See also Boolean data type, section C, C++, Objective-C, AWK.

- 19,463
- 14
- 75
- 113
Here is the version that I used:
typedef enum { false = 0, true = !false } bool;
Because false only has one value, but a logical true could have many values, but technique sets true to be what the compiler will use for the opposite of false.
This takes care of the problem of someone coding something that would come down to this:
if (true == !false)
I think we would all agree that that is not a good practice, but for the one time cost of doing "true = !false" we eliminate that problem.
[EDIT] In the end I used:
typedef enum { myfalse = 0, mytrue = !myfalse } mybool;
to avoid name collision with other schemes that were defining true
and false
. But the concept remains the same.
[EDIT] To show conversion of integer to boolean:
mybool somebool;
int someint = 5;
somebool = !!someint;
The first (right most) ! converts the non-zero integer to a 0, then the second (left most) ! converts the 0 to a myfalse
value. I will leave it as an exercise for the reader to convert a zero integer.
[EDIT]
It is my style to use the explicit setting of a value in an enum when the specific value is required even if the default value would be the same. Example: Because false needs to be zero I use false = 0,
rather than false,
[EDIT] Show how to limit the size of enum when compiling with gcc:
typedef __attribute__((__packed__)) enum { myfalse = 0, mytrue = !myfalse } mybool;
That is, if someone does:
struct mystruct {
mybool somebool1;
mybool somebool2;
mybool somebool3;
mybool somebool4;
}
the size of the structure will be 4 bytes rather than 16 bytes.

- 9,672
- 13
- 78
- 125
-
7Also another benefit to using enums is the IDE integration - `true`, `false` and `bool` are highlighted in most IDE's because they are enum values and a typedef, as opposed to `#defines`, which are rarely ever syntax highlighted. – Jul 28 '15 at 15:22
-
1Curious: Ignoring whether or not it actually works, is it valid C(99+) to allow an enum to reference a prior value in the *same enumeration*? – Nov 07 '15 at 16:30
-
@tgm1024 `gcc -ansi -pedantic -Wall` gives no warnings, so I trust `gcc`; If this works even for `c89` it should work for `c99` aswell. – yyny Mar 26 '16 at 02:17
-
4*"Because false only has one value, but a logical true could have many values, but technique sets true to be what the compiler will use for the opposite of false."* Negation operator `!` can only return values `0` and `1`, so `true = !false` will always assign value 1. This method does not give any extra safety over `typedef enum { false, true } bool;`. – user694733 Sep 04 '19 at 09:27
-
@user694733 Do you have a reference from the standard that !0 always returns 1? And if so, have all C compilers implemented to the standard? – Be Kind To New Users Sep 04 '19 at 15:32
-
3Earliest I found is from C90 (6.3.3.3 Unary arithmetic operators): *"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. The result has type int. The expression !E is equivalent to (O==E)."* That should cover any compiler that has ever claimed to support standard C. Compilers can of course be legally ignore this rule in cases where it doesn't matter for the observable behaviour (like `if(!value)`), but that exception is not applicable in this specific case. – user694733 Sep 05 '19 at 06:52
-
1Those custom ones are 4 bytes long, it's impractical to use them. Is there any way we can implement that with type of CHAR? – Oct 29 '21 at 23:37
-
@DickWilliams Good point about being 4 bytes. I am going to give that some thought on how to use a typedef unsigned char bool and only use const unsigned char b_false = 0; const unsigned char b_true = !b_false; – Be Kind To New Users Oct 31 '21 at 01:12
-
1@DickWilliams Apparently you can "Pack" an enum in gcc: https://stackoverflow.com/questions/4879286/specifying-size-of-enum-type-in-c – Be Kind To New Users Oct 31 '21 at 03:46
-
@BeKindToNewUsers Yeah. Thanks. I've used it like this : `typedef unsigned char bool`, `#define true 1`, `#define false 0`. And that's it. – Oct 31 '21 at 17:01
If you are using a C99 compiler it has built-in support for bool types:
#include <stdbool.h>
int main()
{
bool b = false;
b = true;
}

- 172
- 3
- 8

- 50,926
- 41
- 133
- 199
-
2@JamesStevens that is not right. There is a buit-in type called `_Bool`. It's not an enum. `bool`, `true` and `false` are macros defined in `
` that expand to `_Bool`, `1` and `0` respectively. See https://en.cppreference.com/w/c/types/boolean – Aykhan Hagverdili Jun 25 '21 at 19:02
First things first. C, i.e. ISO/IEC 9899 has had a boolean type for 19 years now. That is way longer time than the expected length of the C programming career with amateur/academic/professional parts combined when visiting this question. Mine does surpass that by mere perhaps 1-2 years. It means that during the time that an average reader has learnt anything at all about C, C actually has had the boolean data type.
For the datatype, #include <stdbool.h>
, and use true
, false
and bool
. Or do not include it, and use _Bool
, 1
and 0
instead.
There are various dangerous practices promoted in the other answers to this thread. I will address them:
typedef int bool;
#define true 1
#define false 0
This is no-no, because a casual reader - who did learn C within those 19 years - would expect that bool
refers to the actual bool
data type and would behave similarly, but it doesn't! For example
double a = ...;
bool b = a;
With C99 bool
/ _Bool
, b
would be set to false
iff a
was zero, and true
otherwise. C11 6.3.1.2p1
- When any scalar value is converted to
_Bool
, the result is 0 if the value compares equal to 0; otherwise, the result is 1. 59)Footnotes
59) NaNs do not compare equal to 0 and thus convert to 1.
With the typedef
in place, the double
would be coerced to an int
- if the value of the double isn't in the range for int
, the behaviour is undefined.
Naturally the same applies to if true
and false
were declared in an enum
.
What is even more dangerous is declaring
typedef enum bool {
false, true
} bool;
because now all values besides 1 and 0 are invalid, and should such a value be assigned to a variable of that type, the behaviour would be wholly undefined.
Therefore iff you cannot use C99 for some inexplicable reason, for boolean variables you should use:
- type
int
and values0
and1
as-is; and carefully do domain conversions from any other values to these with double negation!!
- or if you insist you don't remember that 0 is falsy and non-zero truish, at least use upper case so that they don't get confused with the C99 concepts:
BOOL
,TRUE
andFALSE
!

- 129,958
- 22
- 279
- 321
-
2What part of the C Standard would limit objects of enumerated types to holding the values explicitly listed therein? If the largest value for an enumerated constant is less than UCHAR_MAX or USHRT_MAX, an implementation could use a type smaller than `int` or `unsigned int` to hold an enumeration, but I know of nothing in the Standard that would cause an enumeration to behave as anything other than an integer type. – supercat Oct 05 '18 at 20:06
typedef enum {
false = 0,
true
} t_bool;

- 66,855
- 13
- 106
- 140
-
2@technosaurus Taking this approach does not guarantee !false == true since !false can be any non-zero number. A simple work-around would be to explicitly assign true to !false. – Andrew Mar 11 '15 at 12:39
-
3@Andrew That's not true. `!0 = 1` by the C standard, and `!a = 0` for any non-zero value of `a`. The problem is that any non-zero is considered as true. So if `a` and `b` are both "true", it isn't necessarily the case that ` a == b`. – Jeremy West Jul 11 '17 at 01:39
C has a boolean type: bool (at least for the last 10(!) years)
Include stdbool.h and true/false will work as expected.

- 34,704
- 19
- 73
- 95
-
1310 years in the standard, but not 10 years in compilers! MSVC++'s C compilation does not support C99 at all other than allowing // comments, and is not ever likely to do so. Also _Bool is defined in C99 as a built-in type, while bool is a typedef in the
header. – Clifford Dec 17 '09 at 20:58 -
5@Clifford 4 years on since your comment...nothing has changed. MSVC is a C++ compiler and I believe MS have said that they are not really keen on supporting all new C features (C99 & C11). But I can't take that MSVC doesn't support new C features as a reason (especially when you say it against a *10 years on* answer). 10 years is really a long time in the programming world. Any decent compiler should have support for it in much less than 10 years if the vendor is intended to support it. – P.P Sep 16 '13 at 20:57
-
2@KingsIndian: I am not sure why you directed your comment to me or even felt the need to comment at all. I was only stating the situation as it stood at the time of writing. I was not supporting that situation, merely pointing out that the "answer" may not apply in all circumstances. – Clifford Sep 16 '13 at 21:36
-
@Clifford: Strictly, the standard requires `bool` to be a macro that expands to `_Bool`. The difference matters because you can `#undef` a macro (and that's permitted, at least as a transitional measure), but you can't `untypedef` a typedef. It doesn't alter the main thrust of your first comment, though. – Jonathan Leffler Oct 30 '18 at 03:33
-
2VS2015 and later (& possibly earlier, up to a point) have no problem with `bool` through `
` under C compilation. It resolves to `_Bool`. – Nov 20 '18 at 08:08
Anything nonzero is evaluated to true in boolean operations, so you could just
#define TRUE 1
#define FALSE 0
and use the constants.

- 3,312
- 6
- 32
- 42
-
11but use them with care: since a true result may be any non-zero value, the tests if(t==TRUE){...} and if(t), which are equivalent in other languages, are not equivalent in C. – Fortega Dec 17 '09 at 12:51
-
2You're right, but that's also true in C++ which does have a bool type, right? During debugging i've seen bool variables with values of 5837834939... – ggambetta Dec 17 '09 at 12:54
-
1In C++, the if(t == true) test equals the if(t) test, because C++ does some conversion (everything which is not 0 or a null pointer value is converted to true) – Fortega Dec 17 '09 at 13:03
-
7All you should assume about a boolean true value is that it is non-zero. So code like if( b ) is safe while if( b == TRUE) is not; the latter is bad practice (and pointless). – Clifford Dec 17 '09 at 21:01
This is just a complement to other answers and some clarification, if you are allowed to use C99.
+-------+----------------+-------------------------+--------------------+
| Name | Characteristic | Dependence in stdbool.h | Value |
+-------+----------------+-------------------------+--------------------+
| _Bool | Native type | Don't need header | |
+-------+----------------+-------------------------+--------------------+
| bool | Macro | Yes | Translate to _Bool |
+-------+----------------+-------------------------+--------------------+
| true | Macro | Yes | Translate to 1 |
+-------+----------------+-------------------------+--------------------+
| false | Macro | Yes | Translate to 0 |
+-------+----------------+-------------------------+--------------------+
Some of my preferences:
_Bool
orbool
? Both are fine, butbool
looks better than the keyword_Bool
.- Accepted values for
bool
and_Bool
are:false
ortrue
. Assigning0
or1
instead offalse
ortrue
is valid, but is harder to read and understand the logic flow.
Some information from the standard:
_Bool
is notunsigned int
, but is part of the group unsigned integer types. It is large enough to hold the values0
or1
.- Do not, but yes, you are able to redefine
bool
true
andfalse
but sure is not a good idea. This ability is considered obsolescent and will be removed in future. - Assigning an scalar type (arithmetic types and pointer types) to
_Bool
orbool
, if the scalar value is equal to0
or compares to0
it will be0
, otherwise the result is1
:_Bool x = 9;
9
is converted to1
when assigned tox
. _Bool
is 1 byte (8 bits), usually the programmer is tempted to try to use the other bits, but is not recommended, because the only guaranteed that is given is that only one bit is use to store data, not like typechar
that have 8 bits available.

- 30,738
- 21
- 105
- 131

- 2,128
- 4
- 24
- 34
Nowadays C99 supports boolean types but you need to #include <stdbool.h>
.
Example:
#include <stdbool.h>
int main()
{
bool arr[2] = {true, false};
printf("%d\n", arr[0] && arr[1]);
printf("%d\n", arr[0] || arr[1]);
return 0;
}
Output:
0
1
-
This is more or less a repeat of previous answers. What is new (not a rhetorical question)? – Peter Mortensen Jun 15 '23 at 12:14
Conditional expressions are considered to be true if they are non-zero, but the C standard requires that logical operators themselves return either 0 or 1.
@Tom: #define TRUE !FALSE is bad and is completely pointless. If the header file makes its way into compiled C++ code, then it can lead to problems:
void foo(bool flag);
...
int flag = TRUE;
foo(flag);
Some compilers will generate a warning about the int => bool conversion. Sometimes people avoid this by doing:
foo(flag == TRUE);
to force the expression to be a C++ bool. But if you #define TRUE !FALSE, you end up with:
foo(flag == !0);
which ends up doing an int-to-bool comparison that can trigger the warning anyway.

- 137,073
- 23
- 153
- 219

- 81,374
- 13
- 159
- 204
You could use _Bool, but the return value must be an integer (1 for true, 0 for false). However, It's recommended to include and use bool as in C++, as said in this reply from daniweb forum, as well as this answer, from this other stackoverflow question:
_Bool: C99's boolean type. Using _Bool directly is only recommended if you're maintaining legacy code that already defines macros for bool, true, or false. Otherwise, those macros are standardized in the header. Include that header and you can use bool just like you would in C++.

- 93
- 11
You can use a char, or another small number container for it.
Pseudo-code
#define TRUE 1
#define FALSE 0
char bValue = TRUE;

- 730,956
- 141
- 904
- 1,278

- 36,033
- 20
- 126
- 183
-
Also in C it's usually an int, and it can cause loss of precision warnings by other code that uses int.. – Andreas Bonini Dec 19 '09 at 19:26
-
Unless you are hand-optimising for space, it's always better to use the hardware's normal word-size (e.g.: usually an `int`), since on some architectures you get a significant performance hit from having to unpack/mask checks on these variables. – Kingsley Oct 22 '18 at 23:23
If you are using C99 then you can use the _Bool
type. No #include
s are necessary. You do need to treat it like an integer, though, where 1
is true
and 0
is false
.
You can then define TRUE
and FALSE
.
_Bool this_is_a_Boolean_var = 1;
//or using it with true and false
#define TRUE 1
#define FALSE 0
_Bool var = TRUE;

- 15,171
- 8
- 38
- 76

- 67
- 5
-
4Or you can `#include
` and use `bool`, `true`, and `false` like the standard wants you to. – S.S. Anne Jan 19 '20 at 20:17
This is what I use:
enum {false, true};
typedef _Bool bool;
_Bool
is a built in type in C. It's intended for boolean values.
-
2Nobody should be doing this. The false and true macros in ``stdbool.h`` are ``_Bool``-typed starting in C23. Using an enum like this subtly breaks comparison operators because you don't get automatic casts to ``_Bool``. – Kevin Thibedeau Jul 22 '22 at 23:10
You can simply use the #define
directive as follows:
#define TRUE 1
#define FALSE 0
#define NOT(arg) (arg == TRUE)? FALSE : TRUE
typedef int bool;
And use as follows:
bool isVisible = FALSE;
bool isWorking = TRUE;
isVisible = NOT(isVisible);
and so on

- 15,171
- 8
- 38
- 76

- 79
- 6
-
6The NOT macro should be protected by parentheses around the `arg` and the expression as a whole: `#define NOT(arg) (((arg) == TRUE) ? FALSE : TRUE)`. However, it would be better to test for falseness (it will give the correct answer even if `arg` was 23 instead of 0 or 1: `#define NOT(arg) (((arg) == FALSE) ? TRUE : FALSE)`. But the whole expression can be reduced to `#define NOT(arg) (!(arg))`, of course, which produces the same result. – Jonathan Leffler Sep 14 '18 at 22:14