162

I've seen definitions in C

#define TRUE (1==1)
#define FALSE (!TRUE)

Is this necessary? What's the benefit over simply defining TRUE as 1, and FALSE as 0?

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
  • 37
    And more: `#define TRUE (’/’/’/’)`; `#define FALSE (’-’-’-’)` (taken from http://www.coding-guidelines.com/cbook/cbook1_1.pdf page 871) – osgx Jun 09 '13 at 14:03
  • 2
    No, it's paranoia by the clueless^Wunderinformed, really. In C, 1 and 0 do in all circumstances the same. – Jens Jun 09 '13 at 16:05
  • @osgx What does it mean? – mrgloom Jul 09 '19 at 18:15

8 Answers8

157

This approach will use the actual boolean type (and resolve to true and false) if the compiler supports it. (specifically, C++)

However, it would be better to check whether C++ is in use (via the __cplusplus macro) and actually use true and false.

In a C compiler, this is equivalent to 0 and 1.
(note that removing the parentheses will break that due to order of operations)

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 7
    That's incorrect, bools are not used here. The result of `1==1` is an `int`. (see http://stackoverflow.com/questions/7687403/is-the-true-result-of-or-defined .) – Mat Jun 09 '13 at 13:34
  • 4
    @Mat: Even in C++, with the `boolean` type? – SLaks Jun 09 '13 at 13:35
  • 9
    Question is tagged C, but indeed in C++ the relational operators return `true` or `false`. – Mat Jun 09 '13 at 13:37
  • 5
    @Mat: I'm guessing that such code is written in C headers in order to play well with C++ – SLaks Jun 09 '13 at 13:38
  • 1
    C++ has the same implicit conversion from integral to boolean values as C does, I don't see how this related to that. – Mat Jun 09 '13 at 13:39
  • 20
    @SLaks If it wanted to play nice with C++, it would `#define TRUE true` and `#define FALSE false` whenever `__cplusplus` is defined. – Nikos C. Jun 09 '13 at 13:46
  • 2
    @NikosC. But you didn't write the header - maybe whoever did thought he was being clever. – Sebastian Redl Jun 10 '13 at 16:16
  • 1
    @Mat Implicit conversions don't apply in varargs contexts, so this type of definition plays well there. – Barmar Jun 11 '13 at 19:35
  • @Barmar: given that promotion rules do apply in varargs, you'll get ints in there anyway, not bools (unless you have bools larger than ints?). – Mat Jun 11 '13 at 19:48
  • @Mat boolean types does not exist in C language. Thats why you need to use the int 0 and 1 – ol_v_er Jun 12 '13 at 06:02
  • @Mat Ok, I did not knew. Thanks. But maybe most of code out there is not in C11... – ol_v_er Jun 12 '13 at 09:22
  • @Mat Unfortunatelly, lots of developper still works with older versions of C (for various reasons), so it's a good way to be compatible with older versions instead of working only with "the last version". – NitroG42 Jun 12 '13 at 09:28
  • @slake "I'm guessing?" This is a question and answer site, not question and guess. – Isaac Rabinovitch Jun 13 '13 at 20:26
  • 2
    @IsaacRabinovitch: We cannot but guess at the intent of the person who wrote this code. – SLaks Jun 13 '13 at 21:56
  • They could just `#define TRUE (!0) #define FALSE (!TRUE)` – Aykhan Hagverdili Aug 29 '20 at 10:07
140

The answer is portability. The numeric values of TRUE and FALSE aren't important. What is important is that a statement like if (1 < 2) evaluates to if (TRUE) and a statement like if (1 > 2) evaluates to if (FALSE).

Granted, in C, (1 < 2) evaluates to 1 and (1 > 2) evaluates to 0, so as others have said, there's no practical difference as far as the compiler is concerned. But by letting the compiler define TRUE and FALSE according to its own rules, you're making their meanings explicit to programmers, and you're guaranteeing consistency within your program and any other library (assuming the other library follows C standards ... you'd be amazed).


Some History
Some BASICs defined FALSE as 0 and TRUE as -1. Like many modern languages, they interpreted any non-zero value as TRUE, but they evaluated boolean expressions that were true as -1. Their NOT operation was implemented by adding 1 and flipping the sign, because it was efficient to do it that way. So 'NOT x' became -(x+1). A side effect of this is that a value like 5 evaluates to TRUE, but NOT 5 evaluates to -6, which is also TRUE! Finding this sort of bug is not fun.

Best Practices
Given the de facto rules that zero is interpreted as FALSE and any non-zero value is interpreted as TRUE, you should never compare boolean-looking expressions to TRUE or FALSE. Examples:

if (thisValue == FALSE)  // Don't do this!
if (thatValue == TRUE)   // Or this!
if (otherValue != TRUE)  // Whatever you do, don't do this!

Why? Because many programmers use the shortcut of treating ints as bools. They aren't the same, but compilers generally allow it. So, for example, it's perfectly legal to write

if (strcmp(yourString, myString) == TRUE)  // Wrong!!!

That looks legitimate, and the compiler will happily accept it, but it probably doesn't do what you'd want. That's because the return value of strcmp() is

      0 if yourString == myString
    <0 if yourString < myString
    >0 if yourString > myString

So the line above returns TRUE only when yourString > myString.

The right way to do this is either

// Valid, but still treats int as bool.
if (strcmp(yourString, myString))

or

// Better: lingustically clear, compiler will optimize.
if (strcmp(yourString, myString) != 0)

Similarly:

if (someBoolValue == FALSE)     // Redundant.
if (!someBoolValue)             // Better.
return (x > 0) ? TRUE : FALSE;  // You're fired.
return (x > 0);                 // Simpler, clearer, correct.
if (ptr == NULL)                // Perfect: compares pointers.
if (!ptr)                       // Sleazy, but short and valid.
if (ptr == FALSE)               // Whatisthisidonteven.

You'll often find some of these "bad examples" in production code, and many experienced programmers swear by them: they work, some are shorter than their (pedantically?) correct alternatives, and the idioms are almost universally recognized. But consider: the "right" versions are no less efficient, they're guaranteed to be portable, they'll pass even the strictest linters, and even new programmers will understand them.

Isn't that worth it?

Adam Liss
  • 47,594
  • 12
  • 108
  • 150
  • 6
    `(1==1)` is no more portable than `1`. The compiler's own rules are those of the C language, which is clear and unambiguous about the semantics of equality and relational operators. I've never seen a compiler get this stuff wrong. – Keith Thompson Jun 09 '13 at 21:25
  • 1
    Actually the value returned by `strcmp` is known to be less then, equal or greater then 0. It is not guaranteed to be -1, 0 or 1 and there are platforms in the wild which don't return those values to gain speed of implementation. So if `strcmp(a, b) == TRUE` then `a > b` but reverse implication might not hold. – Maciej Piechotka Jun 10 '13 at 01:23
  • @MaciejPiechotka - Absolutely right; thanks for pointing out the error. I've corrected my description. – Adam Liss Jun 10 '13 at 01:30
  • 2
    @KeithThompson - Perhaps "portability" was the wrong term. But the fact remains that (1==1) is a boolean value; 1 is not. – Adam Liss Jun 10 '13 at 01:31
  • 2
    @AdamLiss: In C, `(1==1)` and `1` are both constant expressions of type `int` with the value 1. They are semantically identical. I suppose you can write code that caters to readers who don't know that, but where does it end? – Keith Thompson Jun 10 '13 at 01:40
  • The numeric value of `TRUE` certainly _is_ important. It's a crucial part of [boolean algebra](http://en.wikipedia.org/wiki/Boolean_algebra#Monotone_laws), which defines it that way to keep a proper correspondence between boolean operations and integer ones. – jthill Jun 10 '13 at 02:08
  • 2
    'not' 5 is, indeed, -6, at bit level. – woliveirajr Jun 10 '13 at 12:47
51

The (1 == 1) trick is useful for defining TRUE in a way that is transparent to C, yet provides better typing in C++. The same code can be interpreted as C or C++ if you are writing in a dialect called "Clean C" (which compiles either as C or C++) or if you are writing API header files that can be used by C or C++ programmers.

In C translation units, 1 == 1 has exactly the same meaning as 1; and 1 == 0 has the same meaning as 0. However, in the C++ translation units, 1 == 1 has type bool. So the TRUE macro defined that way integrates better into C++.

An example of how it integrates better is that for instance if function foo has overloads for int and for bool, then foo(TRUE) will choose the bool overload. If TRUE is just defined as 1, then it won't work nicely in the C++. foo(TRUE) will want the int overload.

Of course, C99 introduced bool, true, and false and these can be used in header files that work with C99 and with C.

However:

  • this practice of defining TRUE and FALSE as (0==0) and (1==0) predates C99.
  • there are still good reasons to stay away from C99 and work with C90.

If you're working in a mixed C and C++ project, and don't want C99, define the lower-case true, false and bool instead.

#ifndef __cplusplus
typedef int bool;
#define true (0==0)
#define false (!true)
#endif

That being said, the 0==0 trick was (is?) used by some programmers even in code that was never intended to interoperate with C++ in any way. That doesn't buy anything and suggests that the programmer has a misunderstanding of how booleans work in C.


In case the C++ explanation wasn't clear, here is a test program:

#include <cstdio>

void foo(bool x)
{
   std::puts("bool");  
}

void foo(int x)
{
   std::puts("int");  
}

int main()
{
   foo(1 == 1);
   foo(1);
   return 0;
}

The output:

bool
int

As to the question from the comments of how are overloaded C++ functions relevant to mixed C and C++ programming. These just illustrate a type difference. A valid reason for wanting a true constant to be bool when compiled as C++ is for clean diagnostics. At its highest warning levels, a C++ compiler might warn us about a conversion if we pass an integer as a bool parameter. One reason for writing in Clean C is not only that our code is more portable (since it is understood by C++ compilers, not only C compilers), but we can benefit from the diagnostic opinions of C++ compilers.

Kaz
  • 55,781
  • 9
  • 100
  • 149
  • 3
    Excellent, and underappreciated, answer. It is not at all obvious that the two definitions of `TRUE` will differ under C++. – user4815162342 Jun 09 '13 at 20:35
  • 4
    How are overloaded functions relevant to code that compiles as both C and C++? – Keith Thompson Jun 09 '13 at 21:19
  • @KeithThompson It's not just about overloading but proper typing in general, overloading is just the most practical example when it comes into play. Of course C++ code without overloads, templates and all that "complicated" stuff removed for *"C-compatibility"* doesn't really care much about types at all, but that doesn't mean one should overthrow the *conceptual* type limitations in a given language. – Christian Rau Jun 10 '13 at 10:47
  • 1
    @ChristianRau: What do you mean "doesn't really care much about types"? Types are central to the C language; every expression, value, and object in a C program has well defined type. If you want to define something differently in C and in C++ (in the *rare* cases where you actually need to write code that compiles as both C and C++), you can use `#ifdef __cplusplus` to express your intent much more clearly. – Keith Thompson Jun 10 '13 at 14:55
  • @KeithThompson Yes I know how important types are. It's just that without all the type-aware stuff like overloading and templates, things like the differentiation between `bool` and `int` don't matter much in practice, since they are implicitly convertible to each other (and in *C* actually *"the same"*, note the quotes, though) and there are not many situations in which you really need to *disambuigate* between the two. *"not much"* was probably too heavy, *"much less compared to code using templates and overloading"* would've been better maybe. – Christian Rau Jun 10 '13 at 15:35
  • @KeithThompson *"If you want to define something differently in C and in C++..."* - I also know this and I didn't ever advocate `(0==0)` as appropriate way to define a "language-independent" `TRUE` and I agree that a `#ifdef __cplusplus` block is much clearer. But nevertheless this macro is a way to do it, even if not the best. The only thing that sparked my comment was you jumping on the overloaded functions example whereas it was just that, an example for a more inherent and conceptual problem, the neccessity for propery typing (which you, as your previous comment suggests, also value high). – Christian Rau Jun 10 '13 at 15:38
  • @Kaz, I know some people (for various reasons) don't care about C99 or newer, but at least your typedef block should check if bool is already defined, in that case use that definition, that would be *real* clean C, such that it compiles semantically equal among all platforms and all ISO C's or C++ for that matter – Sebastian Jul 10 '14 at 12:46
18
#define TRUE (1==1)
#define FALSE (!TRUE)

is equivalent to

#define TRUE  1
#define FALSE 0

in C.

The result of the relational operators is 0 or 1. 1==1 is guaranteed to be evaluated to 1 and !(1==1) is guaranteed to be evaluated to 0.

There is absolutely no reason to use the first form. Note that the first form is however not less efficient as on nearly all compilers a constant expression is evaluated at compile time rather than at run-time. This is allowed according to this rule:

(C99, 6.6p2) "A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be."

PC-Lint will even issue a message (506, constant value boolean) if you don't use a literal for TRUE and FALSE macros:

For C, TRUE should be defined to be 1. However, other languages use quantities other than 1 so some programmers feel that !0 is playing it safe.

Also in C99, the stdbool.h definitions for boolean macros true and false directly use literals:

#define true   1
#define false  0
badp
  • 11,409
  • 3
  • 61
  • 89
ouah
  • 142,963
  • 15
  • 272
  • 331
  • 1
    I have a doubt, TRUE is replaced at every usage with 1==1, while just using 1 will replace 1, isn't the first method extra comparision overhead... or it is made optimized compiler ? – pinkpanther Jun 09 '13 at 13:32
  • 4
    @pinkpanther constant expressions are usually evaluated at compile time and so do not induce any overhead. – ouah Jun 09 '13 at 13:37
  • `1==1` goes to `1` instead of an undefined nonzero value? – djechlin Jun 09 '13 at 13:42
  • 2
    `1==1` is guaranteed to be evaluated to `1` – ouah Jun 09 '13 at 13:44
  • One thing I don't get is, since only `false` is required to have a specific value, namely 0, then why isn't it customary to define `false` as `0` and `true` as `(!0)`? – Nikos C. Jun 09 '13 at 13:56
  • 3
    @NikosC. that's kind of a good question. This matters for code of the form `if(foo == true)`, which will go from merely bad practice to flat-out buggy. – djechlin Jun 09 '13 at 13:58
  • @NikosC.: `(!0)` *is* `1`, by the definition of the `!` operator. – Keith Thompson Jun 09 '13 at 14:52
  • 1
    +1 for pointing out the dangers in `(x == TRUE)` can have a different truth value than `x`. – Joshua Taylor Jun 09 '13 at 16:01
  • I did the work and looked at the spec: " The && operator shall yield 1 if both of its operands compare unequal to 0, otherwise it yields 0. The result has type int." Same language for all other conditionals. Source: http://flash-gordon.me.uk/ansi.c.txt So anything not 0 is true, but a comparisons or logical operators always return 1, not just any nonzero value. – starmole Jun 10 '13 at 08:56
12

Aside from C++ (already mentioned), another benefit is for static analysis tools. The compiler will do away with any inefficiencies, but a static analyser can use its own abstract types to distinguish between comparison results and other integer types, so it knows implicitly that TRUE must be the result of a comparison and should not be assumed to be compatible with an integer.

Obviously C says that they are compatible, but you may choose to prohibit deliberate use of that feature to help highlight bugs -- for example, where somebody might have confuse & and &&, or they've bungled their operator precedence.

sh1
  • 4,324
  • 17
  • 30
  • 1
    That's a good point, and maybe some of these tools can even catch silly code `if (boolean_var == TRUE)` by way of expansion to `if (boolean_var == (1 == 1))` which thanks to the enhanced type info of the `(1 == 1)` node falls into the pattern `if (<*> == )`. – Kaz Jun 09 '13 at 18:06
4

The pratical difference is none. 0 is evaluated to false and 1 is evaluated to true. The fact that you use a boolean expression (1 == 1) or 1, to define true, doesn't make any difference. They both gets evaluated to int.

Notice that the C standard library provides a specific header for defining booleans: stdbool.h.

Shoe
  • 74,840
  • 36
  • 166
  • 272
  • of course you haven't... but some people might think otherwise especially for negative numbers that's why :) – pinkpanther Jun 09 '13 at 13:29
  • What? You have it backwards. `true` is evaluated to `1` and `false` is evaluated to `0`. C doesn't know about native boolean types, they're just ints. – djechlin Jun 09 '13 at 13:46
  • In C, relational and equality operators yield results of type `int`, with value `0` or `1`. C does have an actual boolean type (`_Bool`, with a macro `bool` defined in ``, but that was only added in C99, which did *not* change the semantics of the operators to use the new type. – Keith Thompson Jun 09 '13 at 14:53
  • @djechlin: As of the 1999 standard, C *does* have a native boolean type. It's called `_Bool`, and `` has `#define bool _Bool`. – Keith Thompson Jun 09 '13 at 14:54
  • @KeithThompson, you are right about the `1 == 1` being evaluated as `int`. Edited. – Shoe Jun 09 '13 at 15:16
3

We don't know the exact value that TRUE is equal to and the compilers can have their own definitions. So what you privode is to use the compiler's internal one for definition. This is not always necessary if you have good programming habits but can avoid problems for some bad coding style, for example:

if ( (a > b) == TRUE)

This could be a disaster if you mannually define TRUE as 1, while the internal value of TRUE is another one.

capiggue
  • 111
  • 3
  • In C, the `>` operator always yields 1 for true, 0 for false. There is no possibility of any C compiler getting this wrong. Equality comparisons to `TRUE` and `FALSE` are poor style; the above is more clearly written as `if (a > b)`. But the idea that different C compilers can treat truth and false differently is just incorrect. – Keith Thompson Oct 14 '13 at 22:52
2
  1. List item

Typically in the C Programming Language, 1 is defined as true and 0 is defined as false. Hence why you see the following quite often:

#define TRUE 1 
#define FALSE 0

However, any number not equal to 0 would be evaluated to true as well in a conditional statement. Therefore by using the below:

#define TRUE (1==1)
#define FALSE (!TRUE)

You can just explicitly show that you trying to play it safe by making false equal to whatever isn't true.

Sabashan Ragavan
  • 728
  • 1
  • 5
  • 14