Best Place to Define TRUE/FALSE

K

Keith Thompson

Lane Straatman said:
Keith Thompson said:
Harald van D?k said:
Keith Thompson wrote: [...]
A quick summary:

Opinions vary about whether the C99 standard is a significant
improvement over the C90 standard. But regardless of that, it's a
fact that there are still very few conforming C99 implementations, so
if you want to write maximally portable code you need to stick to C90.

You mean the C99-compatible subset of C90, right?

Yes, you're right. (Mostly that means avoiding the new keywords.)
Does 'bool' count as a keyword? LS

No, "bool" is a macro that expands to the keyword "_Bool". You're
free to use it as long as you don't have a "#include <stdbool.h>".
 
S

Serve Laurijssen

Keith Thompson said:
Why bother?

#define FALSE 0
#define TRUE 1

The parentheses are not necessary, and the value of !0 will never be
anything other than 1 in any language called "C".

Where I work the coding guideline says we *always* have to put parentheses
around macros like that. Maybe a bit overdone but I can see where its coming
from.
 
D

David T. Ashley

Keith Thompson said:
None at all.


If you've defined FALSE and TRUE, don't compare anything for equality
to either of them.

Rather than "if (x == TRUE)", just write "if (x)".
Rather than "if (x == FALSE"), just write "if (!x)".

If you think that "if (x == TRUE)" is better than "if (x)", you should
think that "if ((x == TRUE) == TRUE)" is even better.

And "x" should have a name that makes it clear that it's a condition,
for example "done" or "more_data".

The issue in my mind is "equivalence classing": whatever conventions are
true should be mutually exclusive and mutually exhaustive with respect to
the data type involved.

(x) and (!x) as you suggested meet that requirement.

(==0) and (!=0) as nobody has yet suggested meet that requirement.

(==FALSE) and (!=FALSE) as I suggested meet that requirement.

(==FALSE) and (==TRUE) do not.

I think that in practice "TRUE" should only be used for assigning and never
for testing.

The method of testing that you suggested is probably the best.
 
K

Keith Thompson

David T. Ashley said:
The issue in my mind is "equivalence classing": whatever conventions are
true should be mutually exclusive and mutually exhaustive with respect to
the data type involved.

(x) and (!x) as you suggested meet that requirement.

(==0) and (!=0) as nobody has yet suggested meet that requirement.

(==FALSE) and (!=FALSE) as I suggested meet that requirement.

(==FALSE) and (==TRUE) do not.

I think that in practice "TRUE" should only be used for assigning and never
for testing.

Neither TRUE nor FALSE should be used for testing; both should be used
only for assigning. One of them can safely be used in equality
comparisons, but it's easier to be consistent than to remember which.
The method of testing that you suggested is probably the best.

I agree (obviously).

The problem, of course, is that there's only one false value (0), but
there are arbitrarily many true values (all values other than 0). The
value chosen for the macro/constant/whatever TRUE is in some sense
arbitrary.
 
C

CBFalconer

Richard said:
Lane Straatman said:
Lew Pitcher said:
David T. Ashley wrote:

Where is the best place to define TRUE and FALSE?

In your own headers.

Are they in any of the standard include files, ever?

AFAICT, no. The C standard doesn't define them
Correct.

[snip]
I think that this is an example of a statement that was true in
'89 but false in '99 .

Not so. Neither C90 nor C99 defines TRUE. I didn't actually check
for FALSE, but I'm 99.9% certain it doesn't appear within the text
of the Standard.

The operative verbiage, from N869, is:

7.16 Boolean type and values <stdbool.h>

[#1] The header <stdbool.h> defines four macros.

[#2] The macro

bool

expands to _Bool.

[#3] The remaining three macros are suitable for use in #if
preprocessing directives. They are

true

which expands to the integer constant 1, |

false

which expands to the integer constant 0, and |

__bool_true_false_are_defined

which expands to the decimal constant 1.

[#4] Notwithstanding the provisions of 7.1.3, a program is
permitted to undefine and perhaps then redefine the macros
bool, true, and false.200)
 
M

Malcolm McLean

David T. Ashley said:
Where is the best place to define TRUE and FALSE?
Nowhere.
Is your symbol really necessary?
bool breaks libraries.

You can argue that C ought to have a standard human readable symbol for TRUE
and FALSE. However it is not your job to provide one.

Defining a symbol so fundamental forces everyone who calls your code to
write code in exactly the same style, or have a kludge which rapidly becomes
unreadable. It also makes your code harder for people used to the normal
convention to read. So you don't do it unless you know that you are only
person contributing code to the project.

Consider this

/*
Bloggs.h
#ifndef TRUE
#define TRUE 1
#endif
*/

/*
Muggins.h
#ifndef true
#define true 1
#endif
*/

/*
Dimbo.h
#define TRUE -1
*/

You'll always get a Dimbo.

Even if you don't have a Dimbo somewhere on your team

#define mymacro(x) (x == true) ? 1 : 100

a bit down

y = mymacro(TRUE);

is pretty confusing
 
B

Ben Pfaff

Malcolm McLean said:
You can argue that C ought to have a standard human readable symbol for TRUE
and FALSE. However it is not your job to provide one.

C *does* have a standard, human-readable symbol for TRUE and
FALSE. They are spelled true and false and they are declared in
<stdbool.h>.
 
C

CBFalconer

Richard said:
CBFalconer said:

...irrelevant, since it mentions neither TRUE nor FALSE.

The point is that C99 has standardized those names in lower case,
so I advise jumping on the bandwagon and conforming to that. A
slight babel reduction.
 
J

jaysome

Nowhere.
Is your symbol really necessary?
bool breaks libraries.

You can argue that C ought to have a standard human readable symbol for TRUE
and FALSE. However it is not your job to provide one.

Defining a symbol so fundamental forces everyone who calls your code to
write code in exactly the same style, or have a kludge which rapidly becomes
unreadable. It also makes your code harder for people used to the normal
convention to read. So you don't do it unless you know that you are only
person contributing code to the project.

Consider this

/*
Bloggs.h
#ifndef TRUE
#define TRUE 1
#endif
*/

/*
Muggins.h
#ifndef true
#define true 1
#endif
*/

Preprocessor macros should use all uppercase. I think that's a de
facto convention.
/*
Dimbo.h
#define TRUE -1
*/

You'll always get a Dimbo.

Even if you don't have a Dimbo somewhere on your team

#define mymacro(x) (x == true) ? 1 : 100

If x is a Boolean, then it shouldn't be compared to anything. This
should be:

#define mymacro(x) (x) ? 1 : 100
a bit down

y = mymacro(TRUE);

is pretty confusing

Not if TRUE is defined like it should be:

#ifdef TRUE
#if !(TRUE == 1)
#error "TRUE may have been defined by a Dimbo--it's not equal to 1"
#endif
#else
#define TRUE 1
#endif

For completeness, here's how FALSE should be defined:

#ifdef FALSE
#if !(FALSE == 0)
#error "FALSE may have been defined by a Dimbo--it's not equal to 0"
#endif
#else
#define FALSE 0
#endif

I don't think code should depend on TRUE being 1. Code like this (in
which that variable x is a "Boolean"):

if ( x == TRUE )

should be written like this:

if ( x )

Best regards
 
J

jacob navia

Richard Heathfield a écrit :
Lane Straatman said:
David T. Ashley wrote:

Where is the best place to define TRUE and FALSE?

In your own headers.


Are they in any of the standard include files, ever?

AFAICT, no. The C standard doesn't define them

Correct.


[snip]
I think that this is an example of a statement that was true in '89 but
false in '99 .


Not so. Neither C90 nor C99 defines TRUE. I didn't actually check for FALSE,
but I'm 99.9% certain it doesn't appear within the text of the Standard.

This is wrong advice
 
J

jacob navia

Richard Heathfield a écrit :
jacob navia said:




Chapter and verse, please, Mr Navia. (Translation: you're wrong.)

This is wrong advice since you omit to mention that the C standard
defines true and false, and the same definition in upper case is
wrong and confusing for anyone reading the code.

No further polemic please. I will not reply
 
R

Richard Heathfield

jacob navia said:
Richard Heathfield a écrit :

This is wrong advice
Nope.

since you omit to mention that the C standard
defines true and false,

I also omitted to mention that the C standard defines CHAR_MAX, strlen, and
the <<= operator. So what?
and the same definition in upper case is
wrong and confusing for anyone reading the code.

C is case sensitive, so TRUE is not the same definition in upper case as
true. They are different identifiers. To suggest otherwise is wrong and
confusing.
No further polemic please. I will not reply

Thank heaven for small mercies.
 
S

santosh

David said:
Where is the best place to define TRUE and FALSE?

Are they in any of the standard include files, ever?

As far as I know, no. However C99 does define 'true' and 'false' in
stdbool.h. They resolve into integer constant values 1 and 0
respectively.
Do any standards apply?

None except your own and that of any code to which you're interfacing.
What I've traditionally done is something like:

#ifndef (TRUE)
#define TRUE (1)
#endif

(and same for FALSE).

But is there a "standard place" or a standard way of thinking about these?

Personally when I want to evaluate an object in a boolean manner I use
the construct:

if(!obj)
/* ... */
else
/* ... */

In my experience testing for truth or falsity against exact values is
rarely necessary in C. When such a situation arises, it most often due
to interfacing with third-party code.

If you do want to use them, then using C99's standard forms would
probably be better than rolling your own.
 
L

Lane Straatman

santosh said:
As far as I know, no. However C99 does define 'true' and 'false' in
stdbool.h. They resolve into integer constant values 1 and 0
respectively.


None except your own and that of any code to which you're interfacing.


Personally when I want to evaluate an object in a boolean manner I use
the construct:

if(!obj)
/* ... */
else
/* ... */

In my experience testing for truth or falsity against exact values is
rarely necessary in C. When such a situation arises, it most often due
to interfacing with third-party code.
own.
Since it's been part of a standard that we've all been a little late in
warming up to, the code would suffer the same sheer tonnage of wrongness as
we saw in this thread. I think having _Bool flags is a way to make *darn
sure* of something else more complicated. LS
 
M

Malcolm McLean

Lane Straatman said:
own.
Since it's been part of a standard that we've all been a little late in
warming up to, the code would suffer the same sheer tonnage of wrongness
as we saw in this thread. I think having _Bool flags is a way to make
*darn sure* of something else more complicated. LS
A failed standard creates its own problems.
#include <stdbool.h>
might provoke Oh no, damned thing in C99. We don't support that here.

#define TRUE 1
has the "bool breaks libraries" problem I mentioned elsethread.

So just using implicit false = 0, true = non-zero is best.
 
K

Keith Thompson

Malcolm McLean said:
A failed standard creates its own problems.
#include <stdbool.h>
might provoke Oh no, damned thing in C99. We don't support that here.

#define TRUE 1
has the "bool breaks libraries" problem I mentioned elsethread.

So just using implicit false = 0, true = non-zero is best.

But it's easy enough to use <stdbool.h> conditionally.

For example:

#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#else
typedef enum { false, true } bool;
#endif

This "bool" typedef doesn't have exactly the same semantics as C99's
bool/_Bool type, but it's usable if you avoid writing writing
problematic code.

CBFalconer has posted something similar that supports some additional
C99 features.
 
Y

Yevgen Muntyan

Keith said:
But it's easy enough to use <stdbool.h> conditionally.

For example:

#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#else
typedef enum { false, true } bool;
#endif

This "bool" typedef doesn't have exactly the same semantics as C99's
bool/_Bool type, but it's usable if you avoid writing writing
problematic code.

The following code doesn't compile with "gcc foo.c":

#include <stdbool.h>
#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#else
typedef enum { false, true } bool;
#endif
int main (void)
{
return 0;
}

I guess gcc doesn't define that __STDC_VERSION__ by default
(and it's not a bug, right?). In particular, you can't put
that into a public header, and you need to be careful with
your compiler if you use this code.

But what's the point anyway? Using int as boolean type, and TRUE
and FALSE work well enough, and traditional

#ifndef TRUE
#define TRUE 1 /* or !0 or !FALSE or whatever you like */
#endif

doesn't break, does it? (Problems of Dumbos which write dimbo code
do not count, they will also do

#define false -1

anyway).

Regards,
Yevgen
 
K

Keith Thompson

Yevgen Muntyan said:
Keith Thompson wrote: [...]
But it's easy enough to use <stdbool.h> conditionally.
For example:
#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#else
typedef enum { false, true } bool;
#endif
This "bool" typedef doesn't have exactly the same semantics as C99's
bool/_Bool type, but it's usable if you avoid writing writing
problematic code.

The following code doesn't compile with "gcc foo.c":

#include <stdbool.h>
#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#else
typedef enum { false, true } bool;
#endif
int main (void)
{
return 0;
}

You added an extra "#include <stdbool.h>" outside the #if block. In
C99 mode, <stdbool.h> is included twice, which is harmless. In
non-C99 mode, it's included once, defining "false", "true", and "bool"
as macros, making the typedef illegal.

Remove the extra #include and it's fine.
I guess gcc doesn't define that __STDC_VERSION__ by default
(and it's not a bug, right?). In particular, you can't put
that into a public header, and you need to be careful with
your compiler if you use this code.

The code is designed to work whether __STDC_VERSION__ is defined or
not. Any undefined symbols in a #if condition are replaced with 0.
But what's the point anyway? Using int as boolean type, and TRUE
and FALSE work well enough, and traditional

#ifndef TRUE
#define TRUE 1 /* or !0 or !FALSE or whatever you like */
#endif

doesn't break, does it? (Problems of Dumbos which write dimbo code
do not count, they will also do

#define false -1

anyway).

Sure, that works too. The point is to be consistent with C99 without
requiring a C99 implementation. If (yes, it's big if) C99 becomes as
widespread as C90 is now, the code can be simplified to use
<stdbool.h> unconditionally. If you define macros "TRUE" and "FALSE",
and "true" and "false" are part of the language, then you'll have an
ugly mixture of different ways of doing the same thing.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top