defining a boolean type

S

Scott

Is this reasonable? I am asking mainly about the #if protections not
the enum itself as I am aware there are other ways to do that.

#ifndef BOOL_H
#define BOOL_H

#if (__STDC__)
#if (__STDC_VERSION__ < 199901L)
typedef enum boolean
{
FALSE = (1==0),
TRUE = (1==1)
}bool;
#else
#include <stdbool.h>
#endif
#endif

#endif /* BOOL_H */
 
B

Ben Bacarisse

Scott said:
Is this reasonable? I am asking mainly about the #if protections not
the enum itself as I am aware there are other ways to do that.

#ifndef BOOL_H
#define BOOL_H

#if (__STDC__)
#if (__STDC_VERSION__ < 199901L)
typedef enum boolean
{
FALSE = (1==0),
TRUE = (1==1)
}bool;
#else
#include <stdbool.h>
#endif
#endif

#endif /* BOOL_H */

The main problem is that code that uses this can't use the same
names. You should probably define true and false rater than TRUE and
FALSE.

I am also a little curious as to why there will be no bool type at all
unless __STDC__ is defined though that could be just I don't know how
you plan to use this.
 
S

Seebs

Is this reasonable?
Hmm.

I am asking mainly about the #if protections not
the enum itself as I am aware there are other ways to do that.

Yeah, but those are pretty significant too.
{
FALSE = (1==0),
TRUE = (1==1)

No, no, no, no, no. No. No.

You are nominally trying to provide a type compatible with <stdbool.h>.

However:

1. C99 used "false" and "true".
2. The specified values are "0" and "1". Use those.

"(1==0)" is a bad enough way to express 0 that I would become instantly
distrustful of all future code I saw that I thought came from the same
source.

Try:
enum { false, true } bool;

It'll actually be compatible (nearly) with what C99 used. (It won't have
the trait that assigning arbitrary non-zero values into it yields true,
though.)

-s
 
S

Scott

The main problem is that code that uses this can't use the same
names.  You should probably define true and false rater than TRUE and
FALSE.

I am also a little curious as to why there will be no bool type at all
unless __STDC__ is defined though that could be just I don't know how
you plan to use this.

Good point on the __STDC__ thing. I guess I was thinking that
__STDC_VERSION__ would not be defined unless __STDC__ was thus the
nesting but unless I am mistaken if __STDC_VERSION__ is not defined
the #if (__STDC_VERSION__ < 199901L) line would result in something
like #if (0 < 199901L). I probably should just remove that check.
 
S

Scott

Yeah, but those are pretty significant too.


No, no, no, no, no.  No.  No.

You are nominally trying to provide a type compatible with <stdbool.h>.

However:

1.  C99 used "false" and "true".
2.  The specified values are "0" and "1".  Use those.

"(1==0)" is a bad enough way to express 0 that I would become instantly
distrustful of all future code I saw that I thought came from the same
source.
The intent is not to use "(1==0)" as a means to express the value 0 it
is a means to express the value FALSE, I don't really see how the fact
that it evaluates to 0 makes any difference. I would say this is
really just a stylistic difference and as I said I am aware that these
types of arguments exist on both sides of the issue which is why I
specified I was not asking about this.
Try:
        enum { false, true } bool;
Stylistically you prefer this but mechanically it is identical in
every way to that written above aside from the capitalization which I
agree should be changed.
 
S

Seebs

The intent is not to use "(1==0)" as a means to express the value 0 it
is a means to express the value FALSE, I don't really see how the fact
that it evaluates to 0 makes any difference.

Very simple:

The C99 bool value false is 0. Not "the value FALSE". 0. So you should
be providing the SAME value or you'll have some weird drift between versions.
I would say this is
really just a stylistic difference and as I said I am aware that these
types of arguments exist on both sides of the issue which is why I
specified I was not asking about this.

Ahh, but whether or not you asked about it, you should be aware that
doing stuff like that will make any future reader familiar with C assume
that your code is unreliable. It's just plain wrong. There is nothing
more-false-than-0 in C.
Stylistically you prefer this but mechanically it is identical in
every way to that written above aside from the capitalization which I
agree should be changed.

Style matters. In particular, given that you agree that it's mechanically
equivalent, why on earth are you specifying something in a more complicated
way rather than a simpler way?

Why don't you go a bit further and write:

TRUE = (((1!=0)!=(1!=1))!=0)

?

Because it's wrong, for the same reason that what you have is wrong. Write
for clarity. If you are 100% sure that (1==0) is 0, just write 0. If you
aren't 100% sure of it, you should not be writing header files that other
programmers are supposed to use as utilities or wrappers to export basic
functionality.

-s
 
S

Seebs

Seebs said:
Try:
enum { false, true } bool;
[...]

You just declared a variable named "bool".

.... Wow.

There is probably a missing typedef in here somewhere. Uhm. I, er, left
it as an exercise to the reader.

There is probably good grant money to be had exploring the connection between
level of caffeine in the bloodstream and frequency with which things are
retroactively left as an exercise to the reader.

-s
 
J

James Dow Allen

In C, the repesentations of boolean truth and
falsity are 1 and 0. Always have been. Always
will be. A C programmer who doesn't know this as
well as he knows how to breathe is not a C programmer.

Is this reasonable? I am asking mainly about the #if protections not
the enum itself as I am aware there are other ways to do that.

#ifndef BOOL_H
#define BOOL_H

#if (__STDC__)
#if (__STDC_VERSION__ < 199901L)
typedef enum boolean
{
    FALSE   =   (1==0),
    TRUE    =   (1==1)}bool;

#else
#include <stdbool.h>
#endif
#endif

#endif /* BOOL_H */

That grown men can imagine C code like this
to be purposeful staggers my imagination.

Help this helps.
James
 
K

Keith Thompson

Scott said:
Is this reasonable? I am asking mainly about the #if protections not
the enum itself as I am aware there are other ways to do that.

#ifndef BOOL_H
#define BOOL_H

#if (__STDC__)
#if (__STDC_VERSION__ < 199901L)
typedef enum boolean
{
FALSE = (1==0),
TRUE = (1==1)
}bool;
#else
#include <stdbool.h>
#endif
#endif

#endif /* BOOL_H */

Here's how I'd do it (omitting the header guards):

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

I might write "false=0, true=1" for emphasis, but it's really not
necessary. I wouldn't have a tag on the enum type; you're never going
to refer to the type as "enum boolean", just as "bool".

As a matter of style, I find the use of (1==0) for false and (1==1)
for true to be just obfuscating. 0 is false, 1 is true, and that will
never change in any language called "C".

Also as a matter of style, none of the parentheses in your code are
necessary, and in my opinion none of them are helpful.

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

Ben Bacarisse

(It's best not to quote sigs.)
Good point on the __STDC__ thing. I guess I was thinking that
__STDC_VERSION__ would not be defined unless __STDC__ was thus the
nesting but unless I am mistaken if __STDC_VERSION__ is not defined
the #if (__STDC_VERSION__ < 199901L) line would result in something
like #if (0 < 199901L). I probably should just remove that check.

The __STDC__ test does not help since between C90 and C95 __STDC__
was defined but __STDC_VERSION__ was not. Anyway, it doesn't
matter since you are right that undefined names get replaced by 0 in
#if lines.
 
S

Scott

Very simple:

The C99 bool value false is 0.  Not "the value FALSE".  0.  So you should
be providing the SAME value or you'll have some weird drift between versions.


Ahh, but whether or not you asked about it, you should be aware that
doing stuff like that will make any future reader familiar with C assume
that your code is unreliable.  It's just plain wrong.  There is nothing
more-false-than-0 in C.


Style matters.  In particular, given that you agree that it's mechanically
equivalent, why on earth are you specifying something in a more complicated
way rather than a simpler way?

Why don't you go a bit further and write:

TRUE = (((1!=0)!=(1!=1))!=0)

?

Because it's wrong, for the same reason that what you have is wrong.  Write
for clarity.  If you are 100% sure that (1==0) is 0, just write 0.  If you
aren't 100% sure of it, you should not be writing header files that other
programmers are supposed to use as utilities or wrappers to export basic
functionality.

-s

I agree style matters but I also think that your style is no more
right or wrong than someone else's style. The important thing in
style, in my opinion, is to be consistent. Your stylistic preferences
are formed in large part based on your way of thinking, i.e. the way
you view the world. This is an individual thing and what seems to you
to make the most sense may not make as much sense to someone else
simply because of their world view, that does not make one of them
right and one of them wrong. In this case it seems to me that your
argument makes sense but it also seems to me that someone who says I
don't care that the value is 0 I care that the meaning is false and
(x==y) conveys false to them in a more clear manner than 0 does is
also a reasonable view. Furthermore if they know that it results in
the same thing it is simply stylistic and in my opinion anything that
is stylistic only is not right or wrong only different. Where we part
ways is in the thinking that if someone does not agree with your
stylistic view then everything else they do warrants no more
consideration, seems like an awfully small minded way of thinking to
me. I would agree with you that you could get carried away with this
as you mentioned with TRUE = (((1!=0)!=(1!=1))!=0) but that is not
really what we are talking about.
 
S

Scott

Here's how I'd do it (omitting the header guards):

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

I might write "false=0, true=1" for emphasis, but it's really not
necessary.  I wouldn't have a tag on the enum type; you're never going
to refer to the type as "enum boolean", just as "bool".

As a matter of style, I find the use of (1==0) for false and (1==1)
for true to be just obfuscating.  0 is false, 1 is true, and that will
never change in any language called "C".

Also as a matter of style, none of the parentheses in your code are
necessary, and in my opinion none of them are helpful.

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

--
Keith Thompson (The_Other_Keith) (e-mail address removed)  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

Thanks. I had read the FAQ prior to posting but was just wondering
about the protections I had around that. What I have at this point
looks very close to what you have above.
 
S

Seebs

I agree style matters but I also think that your style is no more
right or wrong than someone else's style.

That is a moderately testable claim.

The key thing is that code is intended to communicate. You have to think
about what the code communicates.

There is a reason that, when we have indentation wars, you will
rarely see someone advocate for:

if (x)
{ if (y) {
z;}}
In this case it seems to me that your
argument makes sense but it also seems to me that someone who says I
don't care that the value is 0 I care that the meaning is false and
(x==y) conveys false to them in a more clear manner than 0 does is
also a reasonable view.

Not in C.

And that's the thing -- we're not working in a pure void, we're working
in an existing language with established conventions and patterns. And
in that language, since everyone knows what the boolean operators yield,
anyone who writes something like this is indirectly communicating that
they don't understand the boolean operators.
Furthermore if they know that it results in
the same thing it is simply stylistic and in my opinion anything that
is stylistic only is not right or wrong only different.

Then your opinion is wrong. See the indentation example above.

There are certainly cases where there's room to assert that a matter of
style is purely a matter of taste, but there are plenty of ways you can
make something which is purely stylistic (as in, the same code will
be generated), where one is clearly superior to another in terms of
long-term maintenance and use of code.
Where we part
ways is in the thinking that if someone does not agree with your
stylistic view then everything else they do warrants no more
consideration, seems like an awfully small minded way of thinking to
me.

Not "no more consideration". Merely that, if a particular choice is
sufficiently unreasonable, that warns me that either they don't understand
the language (in which case I need to exercise additional caution in
dealing with their code), or they are prone to making poor decisions
(in which case I need to exercise additional caution in dealing with their
code).

Some kinds of errors or style choices make me more concerned than others.
If I read a block of sixty or so variable declarations which are in no
particular order, of various types for no obvious reason, and with a bunch
of names which are nonsensical or suggest contradictory nomenclatures, I
know *already* that I'm about to read some bad code. Knowing that is useful.

There's a similar pattern; if you see a car with a bashed-in fender, you
can often predict that it will move erratically in ways which, if you are
not taking care on that driver's behalf, would cause you to bash in that
fender. If you have evidence of poor style, being cautious is generally
rewarding.
I would agree with you that you could get carried away with this
as you mentioned with TRUE = (((1!=0)!=(1!=1))!=0) but that is not
really what we are talking about.

How is it different?

-s
 
K

Keith Thompson

Scott said:
Define bad. Your definition will clearly be different from mine and
that is my point.

The point is that consistency is not the *only* important thing about
style.

If I consistently put my opening braces in column 82 and my closing
braces in column 137, that's bad style, and it's bad in a very
important way.
 
F

Frank

[changing the subject somewhat]
Indeed. Thanks.

I had a question for you. Plauger writes that header inclusion is
idempotent. Is it possible to have:
#undef NDEBUG
#include <assert.h>

and somewhere else NDEBUG *is* defined while assert.h is included, such
that they collide?
 
K

Keith Thompson

Frank said:
[changing the subject somewhat]
Indeed. Thanks.

I had a question for you. Plauger writes that header inclusion is
idempotent. Is it possible to have:
#undef NDEBUG
#include <assert.h>

and somewhere else NDEBUG *is* defined while assert.h is included,
such that they collide?

Header inclusion is idempotent for the standard headers, *except* for
<assert.h>. See C99 7.1.2p1:

Standard headers may be included in any order; each may
be included more than once in a given scope, with no effect
different from being included only once, except that the effect
of including <assert.h> depends on the definition of NDEBUG
(see 7.2).

#including <assert.h> multiple times won't cause a collision.
C99 7.2p1:

The assert macro is redefined according to the current state of
NDEBUG each time that <assert.h> is included.
 

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,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top