tags:

views:

844

answers:

10

C doesn't have any built in boolean types. What's the best way to use them in C?

+4  A: 

Anything nonzero is evaluated to true in boolean operations, so you could just

#define TRUE 1
#define FALSE 0

and use the constants.

ggambett
but 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
You'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...
ggambett
In 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
Try an experiment: `signed int result = !FALSE; printf("%d\n", result);` I believe you'll find out that !0 is not 1 in all cases.
Thomas Matthews
All 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
+5  A: 

A boolean in c is an integer: zero for false and non-zero for true.

See also http://en.wikipedia.org/wiki/Boolean%5Fdata%5Ftype#C

Fortega
+1 for stating that true is non-zero, which unlike other answers, may not be 1. Could be -1, 5, 7, etc.
Thomas Matthews
+20  A: 

Option 1

typedef int bool;
#define true 1
#define false 0

Option 2

typedef int bool;
enum { false, true };

Option 3

typedef enum { false, true } bool;

Option 4 (C99)

#include <stdbool.h>

Explanation

  • Options 1, 2 and 3 will have in practice the same identical behavior. #2 and #3 don't use #defines though, which in my opinion is better.
  • Option 4 will work only if you use C99 and it's the "standard way" to do it. Choose this if possible.

If you are undecided, go with #3!

Andreas Bonini
options 1 and 2 don't have the same behaviour, at least with respect to a debugger, which is aware of enum literals but not of #define macros.
mouviciel
option 3 allows `bool test = 1;` since an enum is basically an integer.
mouviciel
@mouviciel, whoops, I got confused with C++ where that would be illegal :) Edited now, it's been a long time since I used C sorry!
Andreas Bonini
-1 Try this test out: `int result = !false; printf("%d\n", result);`. The `!false` is not guaranteed to equal +1 on all systems. However, when *true* is defined as `!false`, then the boolean relations will be valid. It also frees up any assumptions about the actual numeric value of *true*.
Thomas Matthews
Is it not? Are you sure? Can you quote some part of the standard that says this?
Andreas Bonini
(Do note that I'm not saying it's not true, I'm just curious =) I'll be happy to be proven wrong and promptly edit my answer based on your feedback after you do that!)
Andreas Bonini
Here's an excerpt from the R Project for Statistical Computing: typedef enum { FALSE = 0, TRUE /*, MAYBE */ } Rboolean;
Joey Adams
`!0` will in fact always be 1, but the point is that zero is the *only* false value while all non-zero values are true. This can make it somewhat dangerous to compare directly against a true constant. But, you should never compare against boolean constants anyway.
Dale Hagglund
Option 5 (C99): Use `_Bool`, `_True`, and `_False`
Adam Rosenfield
A: 

You can use a char, or another small number container for it.

Pseduo

#define TRUE  1
#define FALSE 0

char bValue = TRUE;
Filip Ekberg
The problem is that `char` may be signed or unsigned. If `char` is signed, `!FALSE`, evaluates to all 1 bits, which is may be interpreted as -1, and is not equal to your definition of `TRUE`.
Thomas Matthews
Also in C it's usually an int, and it can cause loss of precision warnings by other code that uses int..
Andreas Bonini
+1  A: 

well what about this:

#define TRUE 1
#define FALSE 0
RngTng
Id go with something like #define TRUE !FALSE
Tom
@Tom: What's the value of `v` in this code: `char v = !0`? That's the result of your suggestion.
Georg
The problem is that `!FALSE` may not be `TRUE`. Try and see, especially with unsigned and signed variables.
Thomas Matthews
I tried but didn't see...? O.o
Andreas Bonini
+9  A: 
typedef enum {
    false = 0,
    true
} t_bool;
mouviciel
+1 Using an enum for this is much better than #defines.
ConcernedOfTunbridgeWells
+1 Use enum type and only check true/false against vars of this type.
Marco
-1 This does not follow the boolean logic for all integral data types, especially signed numeric types.
Thomas Matthews
@Thomas Matthews: What is your point? Can you elaborate?
mouviciel
+2  A: 

C has a boolean type: bool (at least for the last 10(!) years)

Include stdbool.h and true/false will work as expected.

dmeister
10 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 <stdbool.h> header.
Clifford
+1  A: 

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;
}

http://en.wikipedia.org/wiki/Boolean_data_type#C99

Gary Willoughby
+1  A: 

@Thomas Matthews: 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.

jamesdlin
+4  A: 

A few thoughts on booleans in C:

I'm old enough that I just use plain ints 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 in 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 mean 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 casee, 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.

Dale Hagglund