Best Place to Define TRUE/FALSE

I

Ian Collins

Keith said:
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 the problem with this example is many compilers now have
stdbool.h, but not many claim to be C99, so __STDC_VERSION__ is less
than 199901L causing the compile error.

The extra include is a bit daft, it would makes the code fail to compile
if the implementation doesn't have stdbool.h.
 
C

CBFalconer

Yevgen said:
.... snip ...

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;
}

See the stdops.h header below. You should also test for __STDC__.
Use -W -Wall -ansi -pedantic with gcc.

/* Standard defines of operators, usable on C90 up */
#ifndef stdops_h
#define stdops_h
#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)
/* The following from C99 - must define for C90 */
#include <stdbool.h> /* define bool, true, false */
#include <iso646.h> /* define not, and, or */
#else
#define false 0
#define true 1
typedef int bool;
#define not !
#define and &&
#define or ||
#define xor ^
#endif
#endif
 
B

Ben Pfaff

CBFalconer said:
#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)
/* The following from C99 - must define for C90 */
#include <stdbool.h> /* define bool, true, false */
#include <iso646.h> /* define not, and, or */
#else
#define false 0
#define true 1
typedef int bool;

bool is supposed to be a macro, too.
 
Y

Yevgen Muntyan

Keith said:
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 put that extra include intentionally of course, to demonstrate
the problem. In real life you include someheader.h which includes
someotherheader.h which includes youhaveneverheardof.h which
includes stdbool.h.
The code is designed to work whether __STDC_VERSION__ is defined or
not. Any undefined symbols in a #if condition are replaced with 0.

Well, my point is that this code can easily cause problems. If
one really wants to use bool, true, and false, he should use something
more robust, e.g. what gnulib does - checks whether #include <stdbool.h>
works in configure, and then perform appropriate header dances.
Or just include <stdbool.h>, which will work too ;)

Best regards,
Yevgen
 
Y

Yevgen Muntyan

CBFalconer said:
Yevgen Muntyan wrote:
... snip ...

See the stdops.h header below. You should also test for __STDC__.
Use -W -Wall -ansi -pedantic with gcc.
[snip]

It (namely the code below) suffers from the very same problem.
__STDC_VERSION__ gets defined only if you use -std=c99, when it's
pointless. -ansi doesn't make it work.

--------------------------------------------------
#include <stdbool.h>

#ifndef stdops_h
#define stdops_h
#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)
/* The following from C99 - must define for C90 */
#include <stdbool.h> /* define bool, true, false */
#include <iso646.h> /* define not, and, or */
#else
#define false 0
#define true 1
typedef int bool;
#define not !
#define and &&
#define or ||
#define xor ^
#endif
#endif

int main (void)
{
}
 
K

Keith Thompson

Ben Pfaff said:
bool is supposed to be a macro, too.

Yes. For (slightly) greater C99 compatibility, you might try:

#define false 0
#define true 1
typedef int _Bool;
#define bool _Bool

except, of course, that "_Bool" is reserved to the implementation in
C90, and some compilers may support the _Bool keyword without claiming
C99 compliance. Oh, well.
 
K

Keith Thompson

Yevgen Muntyan said:
Keith said:
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 put that extra include intentionally of course, to demonstrate
the problem.

You might have mentioned that; I wouldn't have had to waste time
(admittedly not much) tracking down the bug that you introduced into
my code.
In real life you include someheader.h which includes
someotherheader.h which includes youhaveneverheardof.h which
includes stdbool.h.

If you want to write code that's compatible with both C90 and C99, you
don't write a "#include <stdbool.h>" without testing the
value of __STDC_VERSION__.

[snip]
Well, my point is that this code can easily cause problems. If
one really wants to use bool, true, and false, he should use something
more robust, e.g. what gnulib does - checks whether #include <stdbool.h>
works in configure, and then perform appropriate header dances.

All code can cause problems if it's misused.

Build-time configuration can work well too, but I prefer to put the
tests in the code itself *if* (a) it's possible to do so, and (b) it
doesn't make the code too ugly.
Or just include <stdbool.h>, which will work too ;)

Only if it exists, and only if the compiler (in its current mode)
recognizes the _Bool keyword.
 
K

Keith Thompson

Yevgen Muntyan said:
CBFalconer said:
Yevgen Muntyan wrote:
... snip ...
See the stdops.h header below. You should also test for __STDC__.
Use -W -Wall -ansi -pedantic with gcc.
[snip]

It (namely the code below) suffers from the very same problem.
__STDC_VERSION__ gets defined only if you use -std=c99, when it's
pointless. -ansi doesn't make it work.

--------------------------------------------------
#include <stdbool.h>

#ifndef stdops_h
#define stdops_h
#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)
/* The following from C99 - must define for C90 */
#include <stdbool.h> /* define bool, true, false */
#include <iso646.h> /* define not, and, or */
#else
#define false 0
#define true 1
typedef int bool;
#define not !
#define and &&
#define or ||
#define xor ^
#endif
#endif

int main (void)
{
}

Right. If you add an unconditional "#include <stdbool.h>" to code
that carefully tests whether C99 is supported, it will break if
compiled in non-C99 mode. So don't do that.
 
Y

Yevgen Muntyan

Ian said:
I guess the problem with this example is many compilers now have
stdbool.h, but not many claim to be C99, so __STDC_VERSION__ is less
than 199901L causing the compile error.

The extra include is a bit daft, it would makes the code fail to compile
if the implementation doesn't have stdbool.h.

Not necessarily, e.g. gnulib actually creates stdbool.h if there is
no system one.
Or one could do

#ifdef HAVE_STDBOOL_H
#include <stdbool.h>
#else
/* the very same set of defines and typedefs */
#endif

Or one could indeed ignore systems which don't have stdbool.h, and still
have his code working on all systems he and his users have access to.

Regards,
Yevgen
 
Y

Yevgen Muntyan

Keith said:
Yevgen Muntyan said:
Keith 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 put that extra include intentionally of course, to demonstrate
the problem.

You might have mentioned that; I wouldn't have had to waste time
(admittedly not much) tracking down the bug that you introduced into
my code.
In real life you include someheader.h which includes
someotherheader.h which includes youhaveneverheardof.h which
includes stdbool.h.

If you want to write code that's compatible with both C90 and C99, you
don't write a "#include <stdbool.h>" without testing the
value of __STDC_VERSION__.

[snip]
Well, my point is that this code can easily cause problems. If
one really wants to use bool, true, and false, he should use something
more robust, e.g. what gnulib does - checks whether #include <stdbool.h>
works in configure, and then perform appropriate header dances.

All code can cause problems if it's misused.

I do not think that #include <stdbool.h> is qualified as misusing
any code. If you can control all headers you are using (i.e. if you use
only standard headers and you believe your compiler is not buggy and
no standard header includes <stdbool.h> when __STDC_VERSION__ is not
defined) then you probably can expect that code work. Otherwise, it can
easily break without doing any bad/wrong/strange/non-common stuff,
without any action from your side.

It is not true that "it's easy enough to use <stdbool.h> conditionally"
using that code in a general situation (unless it's only about
programs which are "on-topic" here, programs that do not use
any headers which are not mentioned in standard; or only about those
cases when it's indeed easy enough).
Build-time configuration can work well too, but I prefer to put the
tests in the code itself *if* (a) it's possible to do so, and (b) it
doesn't make the code too ugly.

Only if it exists, and only if the compiler (in its current mode)
recognizes the _Bool keyword.

You sure need stdbool.h to exist to include it, but why would you need
_Bool?

Best regards,
Yevgen
 
C

CBFalconer

Ben said:
bool is supposed to be a macro, too.

Not under C90. The point of the typedef is that the usage will be
similar to the C99 usage, i.e.:

bool a, b, c;

will make all three items bools. This won't happen if bool is a
macro for int.
 
C

CBFalconer

Yevgen said:
CBFalconer wrote:
.... snip ...
See the stdops.h header below. You should also test for __STDC__.
Use -W -Wall -ansi -pedantic with gcc.
[snip]

It (namely the code below) suffers from the very same problem.
__STDC_VERSION__ gets defined only if you use -std=c99, when it's
pointless. -ansi doesn't make it work.

Which is just what you want. If the compiler is C99 stdbool and
iso946 will be included, else the substitute definitions appear.
You should get the same net results using either ansi, C90, or
C99. This is a header file, stdops.h. Put it where you will and
#include it in your source.
 
K

Keith Thompson

Yevgen Muntyan said:
You sure need stdbool.h to exist to include it, but why would you need
_Bool?

Because <stdbool.h> contains (the equivalent of)

#define bool _Bool

Though an implementation could either provide a <stdbool.h> that also
compiles in C90 mode, or can recognize _Bool in C90 mode (it's in the
implementation namespace).
 
K

Keith Thompson

CBFalconer said:
Not under C90. The point of the typedef is that the usage will be
similar to the C99 usage, i.e.:

bool a, b, c;

will make all three items bools. This won't happen if bool is a
macro for int.

This:

typedef int bool;
bool a, b, c;

and this:

#define bool int
bool a, b, c;

are equivalent (except that one creates a macro and the other
doesn't). A typedef does *not* create a new type; it only creates an
alias for an existing type. In both cases above, a, b, and c are of
type int.
 
Y

Yevgen Muntyan

CBFalconer said:
Yevgen said:
CBFalconer wrote:
... snip ...
See the stdops.h header below. You should also test for __STDC__.
Use -W -Wall -ansi -pedantic with gcc.
[snip]

It (namely the code below) suffers from the very same problem.
__STDC_VERSION__ gets defined only if you use -std=c99, when it's
pointless. -ansi doesn't make it work.

Which is just what you want. If the compiler is C99 stdbool and
iso946 will be included, else the substitute definitions appear.
You should get the same net results using either ansi, C90, or
C99. This is a header file, stdops.h. Put it where you will and
#include it in your source.

And include some other header which includes stdbool.h
and get an error. It's not what I want for sure.

Note, this "other header" thing is real, e.g. curses.h and ncurses.h
include <stdbool.h> on linux and freebsd machines here.

Regards,
Yevgen
 
Y

Yevgen Muntyan

Keith said:
Because <stdbool.h> contains (the equivalent of)

#define bool _Bool

Though an implementation could either provide a <stdbool.h> that also
compiles in C90 mode, or can recognize _Bool in C90 mode (it's in the
implementation namespace).

Funny. You also need stdbool.h not to contain lines equivalent to

#undef frobnicate
frobnicate(frob frob)

because they would produce compilation errors. Yes, when I said
"just include <stdbool.h>", I meant the case when it exists *and*
works; I didn't mean "include <stdbool.h> and tell your compiler
to error when using it". Sorry for being so not precise, and note
the smiley there and here :)

Regards,
Yevgen
 
Y

Yevgen Muntyan

Keith said:
Yevgen Muntyan said:
CBFalconer said:
Yevgen Muntyan wrote:
... snip ...
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;
}
See the stdops.h header below. You should also test for __STDC__.
Use -W -Wall -ansi -pedantic with gcc.
[snip]

It (namely the code below) suffers from the very same problem.
__STDC_VERSION__ gets defined only if you use -std=c99, when it's
pointless. -ansi doesn't make it work.

--------------------------------------------------
#include <stdbool.h>

#ifndef stdops_h
#define stdops_h
#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)
/* The following from C99 - must define for C90 */
#include <stdbool.h> /* define bool, true, false */
#include <iso646.h> /* define not, and, or */
#else
#define false 0
#define true 1
typedef int bool;
#define not !
#define and &&
#define or ||
#define xor ^
#endif
#endif

int main (void)
{
}

Right. If you add an unconditional "#include <stdbool.h>" to code
that carefully tests whether C99 is supported, it will break if
compiled in non-C99 mode. So don't do that.

It's like that joke about a doctor, isn't it? Don't do what, use any
third-party headers? Or don't use gcc without -std=c99 switch? Or
do use this "careful" code, and then let poor innocent user think
why his "./configure; make; make install" doesn't work. Of course,
on his evil system foo.h includes goo.h which includes ncurses.h
because libgoo author did it for some reason, what a bad luck for
user.

Yevgen
 
C

CBFalconer

Keith said:
This:

typedef int bool;
bool a, b, c;

and this:

#define bool int
bool a, b, c;

are equivalent (except that one creates a macro and the other
doesn't). A typedef does *not* create a new type; it only creates
an alias for an existing type. In both cases above, a, b, and c
are of type int.

You're right, I was wrong. I think my original reason for the
typedef was that was what existed in the N869 standard, but that
seems to be an alternate universe. A define is fine. Does it
really matter?
 
C

CBFalconer

Yevgen said:
Yevgen said:
CBFalconer wrote:
... snip ...
See the stdops.h header below. You should also test for __STDC__.
Use -W -Wall -ansi -pedantic with gcc.
[snip]

It (namely the code below) suffers from the very same problem.
__STDC_VERSION__ gets defined only if you use -std=c99, when it's
pointless. -ansi doesn't make it work.

Which is just what you want. If the compiler is C99 stdbool and
iso946 will be included, else the substitute definitions appear.
You should get the same net results using either ansi, C90, or
C99. This is a header file, stdops.h. Put it where you will and
#include it in your source.

And include some other header which includes stdbool.h
and get an error. It's not what I want for sure.

Note, this "other header" thing is real, e.g. curses.h and ncurses.h
include <stdbool.h> on linux and freebsd machines here.

So what? All system headers can be included multiple times. If
it's not C99 the header doesn't exist. If curses/ncurses.h include
stdbool under C90 they are WRONG.
 
G

Guest

CBFalconer said:
Yevgen said:
Yevgen Muntyan wrote:
CBFalconer wrote:

... snip ...
See the stdops.h header below. You should also test for __STDC__.
Use -W -Wall -ansi -pedantic with gcc.
[snip]

It (namely the code below) suffers from the very same problem.
__STDC_VERSION__ gets defined only if you use -std=c99, when it's
pointless. -ansi doesn't make it work.

Which is just what you want. If the compiler is C99 stdbool and
iso946 will be included, else the substitute definitions appear.
You should get the same net results using either ansi, C90, or
C99. This is a header file, stdops.h. Put it where you will and
#include it in your source.

And include some other header which includes stdbool.h
and get an error. It's not what I want for sure.

Note, this "other header" thing is real, e.g. curses.h and ncurses.h
include <stdbool.h> on linux and freebsd machines here.

So what? All system headers can be included multiple times. If
it's not C99 the header doesn't exist. If curses/ncurses.h include
stdbool under C90 they are WRONG.

C90 implementations are allowed to provide stdbool.h as an extension,
and platform-specific libraries may legitimately contain non-portable
code. ncurses is not wrong to include stdbool.h even in C90 mode.
 

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,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top