tags:

views:

523

answers:

14

As far as I can see there are 3 ways to use booleans in c

  1. with the bool type, from then using true and false
  2. defining using preprocessor #define FALSE 0 ... #define TRUE !(FALSE)
  3. Just to use constants directly, i.e. 1 and 0

are there other methods I missed? What are the pros and cons of the different methods?

I suppose the fastest would be number 3, 2 is more easily readable still (although bitwise negation will slightly add to overhead), 1 is most readable not compatible with all compilers.

+19  A: 

Just include <stdbool.h> if your system provides it. That defines a number of macros, including bool, false, and true (defined to _Bool, 0, and 1 respectively). See section 7.16 of C99 for more details.

Chris Jester-Young
No "bool" is a macro. The type is "_Bool". Otherwise it would terribly break old code.
Lothar
@Lothar: You're 100% correct, although I didn't expect anyone to call me on my little slight-of-hand. :-P
Chris Jester-Young
@Chris: http://xkcd.com/386/
Joe
You can use `_Bool` without including `stdbool.h`
Christoph
+2  A: 

I would go for 1. I haven't met incompatibility with it and is more natural. But, I think that it is a part of C++ not C standard. I think that with dirty hacking with defines or your third option - won't gain any performance, but only pain maintaining the code.

anthares
`bool` is part of C++, but _Bool (with `bool` as an alias) is now part of C (as of C99).
Jerry Coffin
Good to know that. Thanks. :)
anthares
I would not go for 1, as any non-zero value is true. So with signed quantities, -1 is also true.
Thomas Matthews
I mean option 1 ... with bool type
anthares
+1  A: 

With the stdbool.h defined bool type, problems arise when you need to move code from a newer compiler that supports the bool type to an older compiler. This could happen in an embedded programming environment when you move to a new architecture with a C compiler based on an older version of the spec.

In summation, I would stick with the macros when portability matters. Otherwise, do what others recommend and use the bulit in type.

Doug T.
A: 

I used to use the #define because they make code easier to read, and there should be no performances degradation compared to using numbers (0,1) coz' the preprocessor converts the #define into numbers before compilation. Once the application is run preprocessor does not come into the way again because the code is already compiled.

BTW it should be:

#define FALSE 0 
#define TRUE 1

and remember that -1, -2, ... 2, 3, etc. all evaluates to true.

Marco Demajo
TRUE is a write-only value -- when reading/comparing, etc., any non-zero value needs to be treated as true.
Jerry Coffin
for some reason TRUE seems to commonly be defined as#define TRUE !(FALSE)
Tom
@Tom - That's because `!1` returns 0, but `!0` returns a true value, which could be a wide variety of numbers. `#define TRUE !(FALSE)` makes sure that `TRUE == !0` regardless of what exact value `!0` returns.
Chris Lutz
+1  A: 

I prefer (1) when i define a variable but in expressions i never compare against true and false just take the implicit C definition of if(flag) or if(!flag) or if(ptr). Thats the C way to do things.

Lothar
+11  A: 

Just use 0 or 1 directly in the code.

For C programmers, this is as intuitive as true or false.

Bruno Rothgiesser
For C programmers, -1 is also true, since it is not a zero. For that matter, 42 and -234 are also true values. I've seen -1, -2 and other values as true. Some functions return 0 (zero) as successful. Hmmm, so much for consistency.
Thomas Matthews
I usually just see 1 or -1 used as true values. -1 because it's all-ones in binary. I'd love to know where you found -2.
Mike DeSimone
I agree with Thomas. The fact that 0 is used as an error code for "no error" (and often also as an `int` type) sometimes makes it non-obvious whether a value is supposed to be used in a boolean context.
jamesdlin
Think of a function returning 0 for no-error, as answering the question "did you have any problem?" - "0=false=no". `int fail = close(fd); if (!fail) { great(); } else { weep(); }`
squelart
@squelart: The problem is a lot of functions that return boolean values don't have that semantic and return a true value on success, false on failure. (For example, much of the Win32 API is designed this way.)
jamesdlin
You're right, the different return patterns are confusing.But if the initial developer used the above suggestion when first using a function (at which point the dev would know already, or read about, the return value), maintenance would hopefully be easier later on...
squelart
+7  A: 

I usually do a:

typedef enum {FALSE = 0, TRUE} boolean;
Macarse
+2  A: 

Any int other than zero is true; false is zero. That way code like this continues to work as expected:

int done = 0;   // `int` could be `bool` just as well

while (!done)
{
     // ...
     done = OS_SUCCESS_CODE == some_system_call ();
}

IMO, bool is an overrated type, perhaps a carry over from other languages. int works just fine as a boolean type.

wallyk
Re "overrated": In C++, `bool` is a separate type so it can participate in function overloading, for much of the same reason why character constants are of type `char` in C++. Of course, this doesn't apply in C, which has no function overloading.
Chris Jester-Young
No, C is broken in that it doesn't distinguish between boolean and integer.
starblue
C is hardly broken. An integer is a set of booleans which may be manipulated in parallel. Evaluating the set as a whole is their ORed value.
wallyk
@starblue: C99 introduced a dedicated boolean type; if it eases your mind, you can pretend that C automatically converts scalar values to `_Bool` in boolean contexts, a feature found in many dynamic languages as well
Christoph
The nice thing about `_Bool` is that it allows the compiler to store it in whatever way works best (a byte, a word, a bit, whatever); maybe even giving you the option of determining its size at compile time (like in some compilers, where you can specify an `int` as 2 or 4 bytes, or a `long` as 4 or 8 bytes). Have a processor that wants to access things as words? Make `_Bool` the word size. Does your processor access bytes as easily as words? Make it a byte to save space. Got bit-access instructions? Maybe, maybe not. Continuing C's long tradition of not nailing down `int` sizes...
Mike DeSimone
I can live with the way C works, but I think it was a design mistake not to cleanly separate boolean and integer types. C++ tries to rectify that, but is hindered by the need for backward compatibility with C. That the same mistake is made in other languages doesn't make it any better.
starblue
+2  A: 

You can test if bool is defined in c99 stdbool.h with

#ifndef __bool_true_false_are_defined || __bool_true_false_are_defined == 0
//typedef or define here
#endif
Nick
Sorry about my last comment, my PDF search facility is broken. See section 7.16 for more info on `__bool_true_false_are_defined`.
Chris Jester-Young
A: 

I don't know you specific situation. Back when I was writing C programs, we have always used #2.

#define FALSE = 0
#define TRUE = !FALSE

This might be otherwise under alien platform to DOS or Intel-based processors. But I used to use both C and ASM together writing graphic libraries and graphical IDE. I was a true fan of Micheal Abrash and was intending to learn about texture mapping and so. Anyway! That's not the subject of the question here!

This was the most commonly used form to define boolean values in C, as this headerfile stdbool.h did not exist then.

Will Marcouiller
you might want to do this #define TRUE = (!(FALSE))
robUK
A: 

There is no real speed difference. They are really all the same to the compiler. The difference is with the human beings trying to use and read your code.

For me that makes bool, true, and false the best choice in C++ code. In C code, there are some compilers around that don't support bool (I often have to work with old systems), so I might go with the defines in some circumstances.

T.E.D.
A: 

See my response to http://stackoverflow.com/questions/1921539/using-boolean-values-in-c/1926248#1926248 for a reason why not to use #define TRUE (!FALSE).

jamesdlin
A: 

1 is most readable not compatible with all compilers.

No ISO C compiler has a built in type called bool. ISO C99 compilers have a type _Bool, and a header which typedef's bool. So compatability is simply a case of providing your own header if the compiler is not C99 compliant (VC++ for example).

Of course a simpler approach is to compile your C code as C++.

Clifford
A: 

I prefer the third solution, i.e. using 1 and 0, because it is particularly useful when you have to test if a condition is true or false: you can simply use a variable for the if argument.
If you use other methods, I think that, to be consistent with the rest of the code, I should use a test like this:

if (variable == TRUE)
{
   ...
}

instead of:

if (variable)
{
   ...
}
Maurizio Reginelli