7

Putting aside the fact that since c99 the stdbool.h has existed, when defining macros to handle Boolean types in C is there any difference between the following?

#define FALSE 0

#define TRUE 1       // Option 1 
#define TRUE !FALSE  // Option 2

From the live example here, it doesn't seem to make a difference. Is there a technical benefit to either option? (Not including the fact that the second example would work better with c++ bool objects.)

Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175
  • 4
    A downvote explanation would be nice. – Fantastic Mr Fox Feb 22 '16 at 23:12
  • And why not use `stdbool.h`? Using homebrew macros where there are standard macros is a really bad idea. – too honest for this site Feb 22 '16 at 23:15
  • There doesn't seem to be any difference. I usually use a enum, like `typedef enum { TRUE = 1, FALSE = 0 } bool;`, so that I can use `bool` as an actual type – Majora320 Feb 22 '16 at 23:15
  • @Olaf mostly wanted to clarify the discussion that occured here: http://stackoverflow.com/questions/35565191/condition-is-always-true-when-i-know-its-not?noredirect=1#comment58819429_35565191 – Fantastic Mr Fox Feb 22 '16 at 23:16
  • @Ben No problem. I got really worried for a moment about having `TRUE` defined as zero… that would definitely *not* work right. –  Feb 22 '16 at 23:18
  • Just have a look at `stdbool.h` for your implementation. Actually, this discussion is useless. Voting to close as opinion-based - sorry. – too honest for this site Feb 22 '16 at 23:39
  • @Majora320: That is a very bad idea. Also, `true`, `false` and `bool` should not be used, as the standard defines them itself already. Note that the `enum` is not the same type as `_Bool` and might have a different size. It also is `int`, while `_Bool` is unsigned. This can break the ABI. Simply stick to the standard and use `stdbool.h`. – too honest for this site Feb 22 '16 at 23:43
  • @Olaf Yes, that's true, but if I didn't use `stdbool.h` that's what I'd do. – Majora320 Feb 22 '16 at 23:48
  • @Olaf The question, *is there any difference between option a and b* is hardly opinion based. But whatever, i am happy to delete, i have the answer i was looking for. – Fantastic Mr Fox Feb 22 '16 at 23:49
  • "Is there an actual tangible benefit?" is not exactly asking about the differences. A "benefit" can be something not directly related to language details, but the human criteria. So, yes, I think it **is** opinion based. The facts alone can be found much easier by a simple search. – too honest for this site Feb 22 '16 at 23:57
  • @Olaf, ok i see your point. We will see if the community agrees. chux, has provided an answer that suggests one may be better as well. – Fantastic Mr Fox Feb 23 '16 at 00:03
  • @Olaf: `true`, `false`, and `bool` are defined only if `` is included. – Keith Thompson Feb 23 '16 at 02:03
  • @KeithThompson: From my first comment: "And why not use `stdbool.h`?" But note that the future directions state `#undef`ing these macros is an obsolescence feature, which can be seen as an indicator some future version will internalise them as keywords. – too honest for this site Feb 23 '16 at 02:09
  • @Olaf: The C99 `_Bool` / `bool` feature was carefully designed to avoid breaking existing code that used the identifiers `true`, `false`, and `bool`. I suppose a future C standard *might* make them all keywords (similar to C++), but I'd be surprised. (Non-prototype function declarations have been obsolescent since 1989, and we're still stuck with them 28 years later.) – Keith Thompson Feb 23 '16 at 04:00
  • @KeithThompson: Agreed. I wish they sometimes would be more agggressive dropping old "features". If one has to maintain legacy code, you should just compile as such. Problem was long time people were used to the old stuff and safe code was not that much an issue. Call it wishful thinking, but times have changed and safer code now **is** an issue also in C. Too bad there still is no true standardised replacement language in sight. – too honest for this site Feb 23 '16 at 11:57

7 Answers7

13

ISO C and C99 both define ! like so.

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 (0==E).

So !0 evaluates to 1. Given a standards compliant C compiler both your options will have the same result. In addition there's no runtime penalty, compilers will constant fold !0 to 1 at compile time.


If you want to take this to the logical extreme and make no assumptions about what true or false are...

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

This has the advantage of always being true no matter the language. For example, in shell 0 is usually considered "true" or "not an error".

This sort of thing is an anachronism from a time when C did not have an agreed upon standard. For example, the first edition of Code Complete advocates this on page 369. When it was published back in 1993 there was a good chance your C compiler was not going to be ISO compliant and stdbool.h did not exist. "Code Complete" is also intended for the polyglot programmer working in many different languages. Some, like shell and Lisp, define truth differently.

Schwern
  • 153,029
  • 25
  • 195
  • 336
  • Still, even in 1993 I'd be astonished if `(1 == 1)` yielded anything other than an `int` with the value `1`, or if `!(1 == 1)` yielded anything other than an `int` with the value `0`. I believe that defining `TRUE` as `1` and `FALSE` as `0` has *always* been valid, as long as there's been a language called "C" (and probably going back to B, and perhaps BCPL). – Keith Thompson Feb 23 '16 at 01:56
  • @KeithThompson It makes a bit more sense in context in Code Compete as it is a truly polyglot book. It's not really intended as a C specific thing, but a polyglot programming practice. The author's point was that it will work in any language. – Schwern Feb 23 '16 at 03:58
3

There is no benefit to option 2, as ! 0 is guaranteed by the C standard to evaluate to 1.

Defining TRUE in that manner is a staple of old sources, presumably in an attempt to follow the style guide that calls for avoiding "magical constants" whenever possible.

user4815162342
  • 141,790
  • 18
  • 296
  • 355
  • But isn't the `!` an additional opperation that always has to be exectued when `TRUE` is used then? (Under the assumption it is not optimized away by the compiler)? If not, where is the `!0 = 1` part handled then? – Markus Weninger Feb 22 '16 at 23:21
  • 3
    @MarkusWeninger Constant folding is trivial optimization that C compilers have been doing since their inception, and that modern compilers do [even with optimization turned off](https://goo.gl/pYDmXC). In other words, you can definitely count on it being optimized away by the compiler. – user4815162342 Feb 22 '16 at 23:24
  • "and that modern compilers do even with optimization turned off" ... As I thought, thanks for lighten me up. – Markus Weninger Feb 22 '16 at 23:25
  • 1
    Visual Basic represented TRUE as -1 (all bits set) so I wouldn't be surprised if old C compilers did something similar. – user253751 Feb 23 '16 at 01:20
  • 1
    @immibis: I'd be astonished if old C compilers did something similar. A C manual from 1974 (4 years before K&R1) says that the built-in boolean operators (`!`, `==`, `<`, et al) yield `0` for false, `1` for true. – Keith Thompson Feb 23 '16 at 02:01
3
#define FALSE 0

#define TRUE 1       // Option 1 
#define TRUE !FALSE  // Option 2

There is no difference in the values. Both 1 and !0 are constant expressions of type int with the same value, 1 (by the Standard's definition of the semantics of the ! operator).

There is a possible difference in that the second definition is not properly parenthesized. Remember that macro expansion is performed textually. Expanding an unparenthesized macro in the middle of an expression can lead to operator precedence problems. I've written up a contrived example here.

Since the unary ! operator has very high precedence, you're not likely to run into a problem. The only case I can think of is if you use it as a prefix to the indexing operator. For example, given:

int arr[] = { 10, 20 };

Option 1 gives:

TRUE[arr] == 20

while option 2 gives:

TRUE[arr] == 0

To see why, remember that array indexing is commutative (see this question and my answer, and that the indexing operator [] binds more tightly than !.

The lessons here are:

  1. For any macro that's intended to be used as an expression, the entire macro definition should be enclosed in parentheses -- even if you can't think of a case where it would matter.

  2. Keep It Simple. In C, 0 is the only false value, and 1 is the canonical true value. (Any non-zero value is "true", but the built-in "Boolean" operators always yield 0 or 1.) Using the ! operator to define TRUE in terms of FALSE (or vice versa) is just an unnecessary complication.

Use <stdbool.h> if you can. If you can't (because you're stuck with a pre-C99 compiler), I recommend this:

typedef enum { false, true } bool;

It's not quite the same as C99's _Bool / bool (conversions to this bool type aren't normalized to 0 or 1), but it's close enough for almost all purposes.

Community
  • 1
  • 1
Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
2

Not much difference.

#define TRUE 1 has a slight advantage over #define TRUE !FALSE in that 1 is a single item unaffected by operator precedence.

!FALSE could be (!FALSE) to cope with arcane code that attempts to use ++ -- [] . ->, which have higher precedence next to FALSE.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

In the C language, TRUE is properly defined as (!FALSE) because while zero (0) is FALSE and FALSE is zero (0), any other value is TRUE. You can use almost any variable as a boolean expression, and if it is non-zero the value of the expression is TRUE. A NULL pointer is zero for just that reason. So is the end-of-string character ('\0'). There is a great deal of code written to take advantage of that fact. Consider:

while ( *d++ = *s++ ); 

The copy will end when the end-of-string character is copied. This idiom is very common. Never mind the buffer size issues.

This is one reason why it is a bad idea to test for equality to TRUE if you do not have a modern dedicated boolean type where the only possible values are TRUE and FALSE. I suggest you make it a habit to test for inequality to FALSE anyway, for safety's sake. You may not always get to work with the new and shiny.

Bob Wakefield
  • 814
  • 9
  • 16
0

No much difference. But I think #define TRUE 1 is better.

If you use #define TRUE !FALSE:

FALSE is 0 and TRUE is all numbers expect 0.

If you use #define TRUE 1:

FALSE is 0 and TRUE is 1. No problem.

-2

They are just same.

  • !0 is 1 so !FALSE is 1

#define TRUE !FALSE has no technical benefit at all although it existed for along time and appeared many where.

#define TRUE !FALSE can be misunderstood, one could think that TRUE represents every value which not 0.

  • Only 1 equals to TRUE, others values like 2,3, 255... (which !=0) does not equal to TRUE

To prevent this misunderstanding, many organizations require not using #define TRUE !FALSE any more or comparison to TRUE should be changed to !FALSE:

// Should not     
if (var_bool == TRUE) {
...
}

//Should    
if (var_bool != FALSE) {
...
}
Van Tr
  • 5,889
  • 2
  • 20
  • 44
  • I don't follow the logic of that last bit. If someone is confused about how unary `!` works they shouldn't be coding and especially not in C. – Schwern Feb 23 '16 at 04:03
  • Please make a comment for down vote. I just want to know what it is wrong :) – Van Tr Feb 23 '16 at 04:29
  • I already did. Rather than providing a citation to back up your assertion you hand waved. The rest of the answer adds nothing that anyone else hasn't already said. I'm also scratching my head why 255 came up. – Schwern Feb 23 '16 at 04:59
  • I pointed that `#define TRUE !FALSE` has no benefit in a very certain way. I works through some projects, they do have some guys define like this and they do have rule to avoid this definition. " `255` like other values that different to `0` does not equal to `TRUE` ", do I need to make a description like this ? – Van Tr Feb 23 '16 at 05:12
  • I don't believe programmers will confuse `#define TRUE !FALSE` to "think that TRUE represents every value which [is] not 0". The not operator is trivial and works the same in any language. The concept of a thing which is "every value which is not X" doesn't even exist in C. If there is such a rule about defining true and false I think you're misinterpreting the rationale behind it. They likely don't want coders defining their own booleans at all and to instead use `stdbool.h`. Then again, I've seen a lot of bad style rules. I'd be interested to see this rule. – Schwern Feb 23 '16 at 05:19
  • Programmers can confuse any thing from smallest to biggest. Even the guy that asking this question is confusing. I don't really care you believe or not, that what I know so I contribute my knowledge to everyone. Public these rules is violate the right/policy, if you want I can send you through your private contact :) – Van Tr Feb 23 '16 at 05:25
  • Ok, your edit makes it clear what's happened. You've taken a style guide about conditionals and incorrectly extended it to all uses of `!`. And you've got it backwards, because it sure looks like you're advocating double negatives. You *should* use `var_bool == TRUE`. `var_bool == TRUE` is more clear than `var_bool != FALSE`. Or should I say `var_bool == TRUE` is not more unclear than `var_bool != FALSE`? ;) And `if( var_bool )` is even more not unclear. – Schwern Feb 23 '16 at 05:41
  • Although some sections are poorly worded, this is technically correct, although it doesn't add anything to the prior answers. – Fantastic Mr Fox Feb 23 '16 at 06:11
  • @Schwern Now I am curious as to the exact content of such style guides. :) While `var_bool == TRUE` is clearer than `var_bool != FALSE`, the latter will also correctly test truthiness when `var_bool` has a true value other than 1. – user4815162342 Feb 23 '16 at 07:48
  • @user4815162342 Just think about the main purpose of define TRUE and FALSE. In case they use their Bool type which is greater than 1 bit, they expect just two scenario '=0' or '!=0'. In this case `!=FALSE` make sense. – Van Tr Feb 23 '16 at 07:56
  • 1
    @user4815162342 This is why it's better to write `if( var_bool )` and `if( !var_bool )`. – Schwern Feb 23 '16 at 08:10
  • 2
    @IlDivinCodino It says the same thing it always said. Same objections apply. `var_bool != FALSE` is a double negative which adds complexity and should be avoided (or should I say "does not add simplicity and should not be used"). A decent style will recommend `if( var_bool )` to avoid the problem entirely. Nobody who can write working C code will think that `#define TRUE !FALSE` might set `TRUE` to 255 or 2 or 3 and none of that matters because it's not supposed to be used as a number. – Schwern Feb 23 '16 at 08:12
  • 3
    @IlDivinCodino We are in agreement about this. The "purpose of TRUE and FALSE" is to aid readability,i.e. to make it clear that `some_function(FALSE)` intends to send the logically false value to `some_function`, and not the integer 0. *Comparing* against TRUE doesn't work as truth test because in C all non-zero numeric values and all non-NULL pointers are logically true. Comparing against FALSE fails because just changing FALSE to TRUE can break the test. Style guides that prescribe anything of the sort are misguided - in C, one should always use `if (...)` and `if (!...)` to test truthiness. – user4815162342 Feb 23 '16 at 08:12
  • 1
    Can you provide a reference to an actual C style guide that prescribes the use of `if (x != FALSE)` and `if (x == FALSE)` in preference to `if (x)` and `if (!x)`? I've certainly never seen one. – user4815162342 Feb 23 '16 at 08:17
  • @Schwern did you guys read the highlight "To prevent this misunderstanding", it is for this specific case. You believe nobody think blah blah because they can code, but I work in safety embedded system domain where we do not trust on people and every small mistake can be a great critical. – Van Tr Feb 23 '16 at 08:38
  • For saving time, we should stop comment here because it's going nowhere. The answer is what I've got from my experience and I've try my hard to share it clearly. If you want the rule, give me your private contact and I will send you because public it lead me to violate the policy. – Van Tr Feb 23 '16 at 08:53
  • You still misunderstand - the poinf of Schwern's comment is not "you must know how to code", it's that `var_bool != FALSE` actually hurts readability due to it being a double negative. (I also argued that it breaks when you change `FALSE` to `TRUE` to flip the test, another reason to avoid it.) As for a rule being good because someone in "safety embedded system domain" uses it (which we have to take your word for), Toyota and numerous others have shown exactly how much that is worth. – user4815162342 Feb 23 '16 at 20:35
  • I get this point of Schwern. But you can see he said" Nobody who can write working C code will think 2 or 3 or 255 is TRUE" but in the domains I worked in, they do not believe like that, they always believed people can always have mistakes;that's why I mention "many organizations" in my answer to show that this is not my own opinion. I do agree `var_bool != FALSE` can also lack of readability. – Van Tr Feb 24 '16 at 02:52