Esoteric definitions of TRUE and FALSE

N

Noob

Hello,

I've come across a library which defines TRUE and FALSE thus.

/* BOOL type constant values */
#ifndef TRUE
#define TRUE (1 == 1)
#endif
#ifndef FALSE
#define FALSE (!TRUE)
#endif

Do you know why one would do that, instead of the more
straight-forward (IMO)

#define FALSE 0
#define TRUE 1

or, perhaps,

#define FALSE 0
#define TRUE (!FALSE)

(Given that !0 evaluates to 1.)

??

Regards.
 
C

copx

"Noob" wrote in message
Hello,

I've come across a library which defines TRUE and FALSE thus.

/* BOOL type constant values */
#ifndef TRUE
#define TRUE (1 == 1)
#endif
#ifndef FALSE
#define FALSE (!TRUE)
#endif

Do you know why one would do that,

Forward compatibility. The author obviously expected the ISO C
committee to change C's fundamental boolean values ;)
Seriously, I think the author was just bored, so he chose an
unusual solution to entertain himself.
 
K

Keith Thompson

Noob said:
I've come across a library which defines TRUE and FALSE thus.

/* BOOL type constant values */
#ifndef TRUE
#define TRUE (1 == 1)
#endif
#ifndef FALSE
#define FALSE (!TRUE)
#endif

Do you know why one would do that, instead of the more
straight-forward (IMO)

#define FALSE 0
#define TRUE 1

or, perhaps,

#define FALSE 0
#define TRUE (!FALSE)

(Given that !0 evaluates to 1.)

There is no good reason to do that.

See section 9 of the comp.lang.c FAQ, <http://c-faq.com/>.

In the absence of <stdbool.h>, my favorite form is

typedef enum { false, true } bool;
 
K

Keith Thompson

pete said:
My preference is to regard false as being equal to zero,
and to consider true as meaning not equal to zero.
Which is to say that for comparison purposes
I would only ever use the FALSE macro.

Why would you use either TRUE or FALSE for comparison?

(cond == FALSE) is better written as (!cond)
(cond == TRUE) is better written as (cond)
<stdbool.h> is one of those C99isms, which I don't like.

De gustibus non carborundum, or something like that.
 
B

Ben Pfaff

Noob said:
/* BOOL type constant values */
#ifndef TRUE
#define TRUE (1 == 1)
#endif
#ifndef FALSE
#define FALSE (!TRUE)
#endif

Do you know why one would do that [...]

I think that some people think it is clever. I thought it was
clever, too, the first time I saw it (perhaps 20 years ago), but
I no longer feel that way.
 
B

Ben Pfaff

Kenneth Brody said:
I used C compilers in K&R1 (ie: pre-ANSI) days, where some systems
would evaluate the expression "1==1" as negative 1.

Even K&R1 says (p. 189) that relational operators "all yield 0 if
the specified relation is false and 1 if it is true." It also
says (p. 190) that the equality operators are "exactly analogous
to the relational operators except for their lower precedence."

It seems that the implementation that you worked with was not
very carefully done.
 
M

Morris Keesan

.... (why define TRUE and FALSE as other than 1 and 0?) ...

As others have said, they thought they were being clever.
Either that, or they didn't understand C, or they were afraid that their
compiler implementers didn't understand C.

Personally, I never liked those macros, and I find them over-used.
I'm currently a teaching assistant for a university course which uses C,
and in the course of grading some homework, I've just been ranting to one
of my students about constructs like

if (some_boolean_expression)
return TRUE;
else
return FALSE;

which irritates me to an unreasonable extent, because it's just a more
verbose way of writing
return (some_boolean_expression)

I've also seen expressions like

(x == y) ? TRUE : FALSE

which, inductively, I often feel like re-writing as

((x == y) ? TRUE : FALSE) ? TRUE : FALSE
 
B

Ben Pfaff

Morris Keesan said:
I've also seen expressions like

(x == y) ? TRUE : FALSE

which, inductively, I often feel like re-writing as

((x == y) ? TRUE : FALSE) ? TRUE : FALSE

I like it better without the confusingly redundant parentheses:
x == y ? TRUE : FALSE ? TRUE : FALSE ? TRUE : FALSE
 
M

Michael Angelo Ravera

Hello,

I've come across a library which defines TRUE and FALSE thus.

/* BOOL type constant values */
#ifndef TRUE
   #define TRUE (1 == 1)
#endif
#ifndef FALSE
   #define FALSE (!TRUE)
#endif

Do you know why one would do that, instead of the more
straight-forward (IMO)

#define FALSE 0
#define TRUE  1

or, perhaps,

#define FALSE 0
#define TRUE (!FALSE)

(Given that !0 evaluates to 1.)

??

Regards.

I don't happen to agree with it, but the reason for defining the TRUE
macro as (1==1) would be that you can be assured that the compiler
will evaluate (1==1) to true and, if you ever need to compare that
value (some implementations might give -1 for the result), you will
always get the right value.

However, the only proper "comparison" of proper boolean values is for
logical equivalence, logical implication and the like. In the
abstract, boolean values should not be compared, but tested.

"if (boolean value != 0") is an obfuscation of "if (boolean_value)"

"if (boolean_value == 1)" might not even produce the desired results
depending upon your implementation.
 
B

Ben Pfaff

Michael Angelo Ravera said:
I don't happen to agree with it, but the reason for defining the TRUE
macro as (1==1) would be that you can be assured that the compiler
will evaluate (1==1) to true and, if you ever need to compare that
value (some implementations might give -1 for the result), you will
always get the right value.

No implementation of standard C will give -1 for the result of 1==1.
 
K

Kenny McCormack

No implementation of standard C will give -1 for the result of 1==1.

Hmmm.. I just wrote one last night that did.

--
(This discussion group is about C, ...)

Wrong. It is only OCCASIONALLY a discussion group
about C; mostly, like most "discussion" groups, it is
off-topic Rorsharch [sic] revelations of the childhood
traumas of the participants...
 
E

Eric Sosman

[...]
In the absence of<stdbool.h>, my favorite form is

typedef enum { false, true } bool;

Reading someone else's code, I once encountered

typedef enum { TRUE, FALSE } Boolean;

Any guesses why I was reading the code? There were B-U-U-G-S...
 
J

James Kuyper

Hello,

I've come across a library which defines TRUE and FALSE thus.

/* BOOL type constant values */
#ifndef TRUE
#define TRUE (1 == 1)
#endif
#ifndef FALSE
#define FALSE (!TRUE)
#endif

Do you know why one would do that, instead of the more
straight-forward (IMO)

#define FALSE 0
#define TRUE 1

or, perhaps,

#define FALSE 0
#define TRUE (!FALSE)

(Given that !0 evaluates to 1.)

??

Yes. Those definitions have, under certain very implausible
circumstances, one definite advantage. The implausible circumstances
involve a potential reader who
a) understands or can guess that == is the C equality comparison operator
b) understands or can guess that ! is the C logical negation operator
c) is not certain what values C treats as true and false.

Such a reader can verify that these definitions are correct, just by
reading and understanding them, without having to resolve his confusion
on item c.

I wouldn't write my code to target such a peculiar audience - but I've
certainly seen weirder code than that.
 
J

Jorgen Grahn

Hmmm.. I just wrote one last night that did.

You mean you wrote here *about* an ancient compiler which did.
But as others replied, that compiler was horribly broken. It shouldn't
affect how people write C code today.

/Jorgen
 
S

Stefan Ram

Keith Thompson said:
(cond == TRUE) is better written as (cond)

This is not just »better«, it is they only correct way.

false:

if( isprint( ch )== TRUE )...

correct:

if( isprint( ch )) ...

(»The functions in this subclause return nonzero (true) if
and only if the value of the argument c conforms to that in
the description of the function.«)
 
K

Keith Thompson

This is not just »better«, it is they only correct way.

false:

if( isprint( ch )== TRUE )...

correct:

if( isprint( ch )) ...

(»The functions in this subclause return nonzero (true) if
and only if the value of the argument c conforms to that in
the description of the function.«)

In the case of the is*() functions, yes, comparing their
results to TRUE (or true, or 1, or ...) is semantically incorrect.

But there are plenty of cases where the value of cond is, for
whatever reason, guaranteed by the language to be either 0 or 1.
For example, the equality and relational operators always yield 0
or 1. If (x == y) were to yield 2, most if statements that use it
would still work, but it would indicate a broken compiler.

So given:
int cond = (x == y);
this:
if (cond) ...
and this:
if (cond == TRUE) ...
/* assuming an appropriate definition of TRUE */
are equally correct, but the shorter form is definitely *better*.

(I actually prefer (all else being equal) languages that clearly
distinguish between numeric values and booleans. Neither C99 nor
C++ does so; they both have distinct bool types, but they allow
non-boolean expressions to be used as conditions.)
 
K

Keith Thompson

pete said:
The following line would work just fine:

if (isprint(ch) != FALSE)

However,

if (isprint(ch))

is actually the way that I would really write that in source code,
because the only meaning of the return value of isprint
is whether or not it compares equal to zero.

For other cases, such as the return value of malloc,
there is more meaning to the return value
besides whether or not it compares equal to zero;
and for that reason I would be more inclined to write

if ((ptr = malloc(sizeof *ptr)) != NULL)

rather than

if (ptr = malloc(sizeof *ptr))

And to answer Keith Thompson's question from upthread,
I am completely disinclined
to write either TRUE or FALSE in source code.
I was only trying to imagine how I would use those macros,
if I were to use them.

TRUE and FALSE or equivalents, IMHO, are quite useful on the RHS of an
assignment. They are not useful in comparisons.

And I agree with you about ptr.

My own strong inclination is that, if an expression only expresses truth
or falsity, it should be treated directly as a boolean and not further
compared to anything else. (It does sometimes make sense to compare
boolean values to each other, but that's fairly rare, and C's semantics
make it risky.) But if an expression expresses something more, as for
"ptr" above, I like to explicitly compare it to something.
 
G

Geoff

There is no good reason to do that.

See section 9 of the comp.lang.c FAQ, <http://c-faq.com/>.

In the absence of <stdbool.h>, my favorite form is

typedef enum { false, true } bool;

So what would you recommend in the case of inherited legacy code like
this?

typedef enum bool_n {QFALSE, QTRUE} qboolean;
....

qboolean IsFemale (edict_t *ent)
{
char *info;

if (!ent->client)
return QFALSE;

info = Info_ValueForKey (ent->client->pers.userinfo, "skin");
if (info[0] == 'f' || info[0] == 'F')
return QTRUE;
return QFALSE;
}
 
K

Keith Thompson

Geoff said:
Noob said:
I've come across a library which defines TRUE and FALSE thus.
[snip]

There is no good reason to do that.

See section 9 of the comp.lang.c FAQ, <http://c-faq.com/>.

In the absence of <stdbool.h>, my favorite form is

typedef enum { false, true } bool;

So what would you recommend in the case of inherited legacy code like
this?

typedef enum bool_n {QFALSE, QTRUE} qboolean;
...

qboolean IsFemale (edict_t *ent)
{
char *info;

if (!ent->client)
return QFALSE;

info = Info_ValueForKey (ent->client->pers.userinfo, "skin");
if (info[0] == 'f' || info[0] == 'F')
return QTRUE;
return QFALSE;
}

Recommend for what purpose?

If the code works as it is, you're probably better off leaving it alone.

There are a couple of things I would have done differently:

I'd omit the tag "bool_n" on the enum declaration; it's not necessary
and it's probably never used.

Rather than

if (info[0] == 'f' || info[0] == 'F')
return QTRUE;
return QFALSE;

I'd have written:

return (info[0] == 'f' || info[0] == 'F');

(perhaps without the parentheses). Implicit conversion will
reliably convert the int result of the condition to qboolean.

But again, I wouldn't modify existing working code to match my
personal taste, with the risk of introducing new bugs, without a
good enough reason. ("Just because I feel like it" may sometimes
be a good enough reason.)
 

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

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top