[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20130901085049.21748.qmail@science.horizon.com>
Date: 1 Sep 2013 04:50:49 -0400
From: "George Spelvin" <linux@...izon.com>
To: linux@...izon.com, torvalds@...ux-foundation.org
Cc: linux-fsdevel@...r.kernel.org, linux-kernel@...r.kernel.org,
viro@...iv.linux.org.uk, waiman.long@...com
Subject: Re: [PATCH v7 1/4] spinlock: A new lockref structure for lockless update of refcount
> If "bool" had real advantages (like having a dense array
> representation, for example), that would be one thing. It doesn't.
> Sure, now you can take an address of a bool (which you couldn't
> generally do efficiently if it really was a bit array), but it also
> means that in practice, "bool" is normally nothing but "char" with
> some really odd and special implicit type casting rules.
Huh. For me, the big advantage is, to paraphrase Michael Palin, that
the number of possible values is two, no more, and no less. Two is
the number of possibilities, and the number of possibilities is two.
Three is Right Out.
I agree that as a *storage* type (in a data structure), it's of limited
usefulness. But as a *parameter* type, to pass to and return from
functions, it's wonderful.
There are lots of naming conventions (like the word "flag", or a function
name starting with "is") to indicate that the return value is a simple
true/false, but declaring it that way provides compile-time checking.
> I doubt most people really even understand how "bool" casting works.
There's a reason for that; you rarely need to cast to bool, and you
could forbid it outright with very little impact on bool's usefulness.
What fraction of C programmers remember off the top of their heads that
casting from float to integer rounds toward zero?
Heck, if you asked me which conversions were defined and which were
undefined, I'd have to look it up. (I'd guess it's the same as the
different overflow rules for signed and unsigned types, but I'd have
to check.)
The place bool is most useful is control flow flags and other things
where all you're doing is assigning literal values and testing it. And,
if you want to get fancy, assigning to bool variables from boolean-valued
expressions like "flag = value >= limit;"
That said, I agree that the fact that 2 != (bool)2 is a bit subtle, but
doesn't that basic problem apply to *any* narrowing cast? (And thus,
is not really an *additional* subtlety that a progammer needs to learn
about.) And in this case, I can't really think of a *better* choice
that could have been made.
I can only see three plausible alternatives:
1) Use the lsbit, (bool)x == x & 1
2) Use zero/nonzero, and make (bool)x == !!x
3) Forbid casting to bool entirely.
Option 1 matches all other narrowing casts in C, and would be how I'd
expect a "bit" type to work.
Option 2 is how C conditional statements already work, so for any value x,
"if (x)" is the same as "if ((bool)x)". It's a rule that C programmers
already need to know; they only need to know to *apply* it in this one
extra case.
In fact, it arguably makes things *simpler* to explain, since it at least
gives a name to the magic that C condition expressions are subject to.
Option 3 is attractive, but ends up breaking the analogy to conditional
expressions. I'd recommend it as a coding style, however.
> And bool is actually really *dangerous* to use if you don't understand
> it. There are people who use "bool", but then because they want to be
> portable, they have a compatibility #ifdef or other configuration
> thing that does something like
>
> typedef int bool;
> #define true 1
> #define false 0
>
> and it will actually work. Most of the time. And then the semantic
> differences from a _real_ C compiler that supports the C99 _Bool/bool
> type are really really subtle.
But *all* of the subtleties arise when casting other types to bool.
If you just avoid that one thing (which it's hopefully obvious won't be
faithfully emulated by a compatibility kludge anyway), it all goes away.
And this rule is itself just a special case of "be very careful with
narrowing casts", which is already common wisdom.
For that kludge, I think a better equivalent would be
typedef enum { false, true } bool;
which at least communicates the idea (again, this is an annoying sutlety
that C programmers *already* have to deal with, so no additional cognitive
effort) that "the compiler might not catch you assigning out-of-range
values, but if you do, demons might fly out of your nose."
Anyway, thanks for sharing your opition. To me, it just looked like exactly
the sort of code where the bool type was a natural fit.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists