boolean usage

T

Tim Rentsch

Peter Nilsson said:
Tim Rentsch said:
Ben Bacarisse said:
_Bool is an unsigned type. ...
In any kind of arithmetic or comparison it will always be
promoted to an int since the two legal values of _Bool
always fit into and int.

To nitpick, C99 does not say that 0 and 1 are the only legal
values for bool, [snip elaboration]

Not said explicitly, but this does hold as a logical
consequence of the rules governing conversions.

But there are other ways to get a value into a _Bool than via a
conversion.

That's true but it doesn't change the result. The question is
what values can _Bool hold as documented values (ie, and not trap
representations),

My last assertion was that _Bool's integer promotion can potentially
be to unsigned int.

"An object declared as type _Bool is large enough to store the
values 0 and 1."[1] There is nothing stating that _Bool must only
have 1 value bit, just as UINT_MAX being at least 65535 is not a
statement that it can only be 65535.
and these are constrained by conversion rules to be only 0 and 1

That mearely constrains the values that result from conversion.

No, the conversion rules also have implications for what
values a _Bool can hold, not just for the output of a
conversion.

You haven't demonstrated it would be non-conforming.

True, I hadn't, but will (again) below...

True, but not the issue.


If it isn't a trap representation then all you can say is the value
is appropriate to the object type.

That, _and_ the implementation must conform to all the other
requirements given in the Standard. Consider the following
program:

_Bool a, b;

/* somehow give 'b' a value, not by assigning to it but *
* by some other means such as storing into it using an *
* unsigned character array. */

a = b;

The assignment operation converts the _Bool value of the
right-hand side to the type of the assignment expression, which is
also _Bool. By 6.3.1.2p1, the result of the conversion must be 0
or 1. By 6.3p2, the result of the conversion must also be the
same value as the pre-conversion value. These two conditions can
be satisfied simultaneously only if _Bool is constrained to just
two defined values (those being 0 and 1).

The Committee's Response in DR335 says _Bool has an implementation
defined width. Has there been any advance on that?

Something being implementation-defined isn't carte blanche;
whatever its definition is, the implementation still must
conform to the Standard's other requirements, which in this
case imply that the width must be one. As of n1570, all the
relevant sections - 6.3p2, 6.3.1.2p1, 6.5.16.1p2 - are all
exactly the same as in n1256 (except for one unrelated new
footnote having to do with converting NAN's to _Bool).
 
K

Keith Thompson

Tim Rentsch said:
Assignment _always_ performs a conversion, even if the two types
are the same. 6.5.16.1p2 -- look it up.

Interesting.

So this:
int i;
i = 42;
performs a conversion from int to int (because 6.5.16.1p2 says so), but
this:
(int)42;
does not perform a conversion (I don't think that's explicitly stated,
but otherwise the last sentence of 6.5.4p4 would be meaningless).

There's no actual contradiction, but it does seem conceptually
inconsistent.

In most cases there's no practical difference between not
doing a conversion and doing a conversion that has no effect.
C99's introduction of _Bool, with its special conversion rules,
makes the distinction significant, at least in some corner cases.
 
K

Keith Thompson

Tim Rentsch said:
That, _and_ the implementation must conform to all the other
requirements given in the Standard. Consider the following
program:

_Bool a, b;

/* somehow give 'b' a value, not by assigning to it but *
* by some other means such as storing into it using an *
* unsigned character array. */

a = b;

The assignment operation converts the _Bool value of the
right-hand side to the type of the assignment expression, which is
also _Bool. By 6.3.1.2p1, the result of the conversion must be 0
or 1. By 6.3p2, the result of the conversion must also be the
same value as the pre-conversion value. These two conditions can
be satisfied simultaneously only if _Bool is constrained to just
two defined values (those being 0 and 1).

Or if the program's behavior is undefined, because b holds a trap
representation.
Something being implementation-defined isn't carte blanche;
whatever its definition is, the implementation still must
conform to the Standard's other requirements, which in this
case imply that the width must be one. As of n1570, all the
relevant sections - 6.3p2, 6.3.1.2p1, 6.5.16.1p2 - are all
exactly the same as in n1256 (except for one unrelated new
footnote having to do with converting NAN's to _Bool).

But for something to be implementation-defined, there must be at
least two possible choices (C99 3.4.4, 3.4.1). (I'm assuming that
the wording for "implementation-defined behavior" applies to other
things that are implementation-defined.)

Saying that the width of bool must be 1 and is implementation-defined is
inconsistent.
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
Assignment _always_ performs a conversion, even if the two types
are the same. 6.5.16.1p2 -- look it up.

Interesting.

So this:
int i;
i = 42;
performs a conversion from int to int (because 6.5.16.1p2 says so), but
this:
(int)42;
does not perform a conversion (I don't think that's explicitly stated,
but otherwise the last sentence of 6.5.4p4 would be meaningless).
[snip elaboration]

No, a cast always performs a conversion. 6.5.4p4:

Preceding an expression by a parenthesized type name
converts the value of the expression to the named type.
This construction is called a cast. A cast that specifies
no conversion has no effect on the type or value of an
expression.

The first sentence mandates that a conversion be performed,
with no exceptions.

The third sentence, it seems fairly clear, is talking about
cases where an expression is converted to an expression of
the same type. However, it does not say no conversion is
performed, only that a cast that /specifies/ "no conversion"
not change the type or value. The cast still must effect
a conversion, even if it "does nothing".

Casting an expression to the same type as the expression
must effect a conversion because (despite 6.5.4p4) such
conversions can have semantic consequences. See 6.3.1.5p2.
 
K

Keith Thompson

Tim Rentsch said:
Keith Thompson said:
Tim Rentsch said:
...
When I convert the value of u.b to _Bool (a conversion from
_Bool to _Bool)...

_Bool to _Bool does not require a conversion, a _Bool *is* a _Bool.

Assignment _always_ performs a conversion, even if the two types
are the same. 6.5.16.1p2 -- look it up.

Interesting.

So this:
int i;
i = 42;
performs a conversion from int to int (because 6.5.16.1p2 says so), but
this:
(int)42;
does not perform a conversion (I don't think that's explicitly stated,
but otherwise the last sentence of 6.5.4p4 would be meaningless).
[snip elaboration]

No, a cast always performs a conversion. 6.5.4p4:

Preceding an expression by a parenthesized type name
converts the value of the expression to the named type.
This construction is called a cast. A cast that specifies
no conversion has no effect on the type or value of an
expression.

The first sentence mandates that a conversion be performed,
with no exceptions.

The third sentence, it seems fairly clear, is talking about
cases where an expression is converted to an expression of
the same type. However, it does not say no conversion is
performed, only that a cast that /specifies/ "no conversion"
not change the type or value. The cast still must effect
a conversion, even if it "does nothing".

Casting an expression to the same type as the expression
must effect a conversion because (despite 6.5.4p4) such
conversions can have semantic consequences. See 6.3.1.5p2.

I think the standard is unintentionally inconsistent, and we're
trying to extract meaning from the particular way things are phrased.
I suggest that the end result of this analysis should be a set of
suggested changes to the standard, not necessarily any definitive
conclusion about what it "really means".

In the case of (int)42, if the cast "specifies no conversion",
then what does? Why would a conversion be performed if nothing
specifies it?

I think the intent is that the third sentence is talking about an
exception to the rule stated in the first. I grant that I'm not
on very firm ground with this interpretation, but it's what makes
the most sense to me (though it certainly could have been stated
more clearly).

C90 had very similar wording -- and in C90, there was no real
difference between not doing a conversion and doing a conversion
from a type to the same type. I suspect that the authors of the
standard didn't realize the introduction of semantically meaningful
_Bool-to-_Bool conversions called for the wording about conversions
and casts to be revisited.
 
T

Tim Rentsch

Keith Thompson said:
Or if the program's behavior is undefined, because b holds a trap
representation.


But for something to be implementation-defined, there must be at
least two possible choices (C99 3.4.4, 3.4.1). (I'm assuming that
the wording for "implementation-defined behavior" applies to other
things that are implementation-defined.)

For the sake of discussion let me agree to this premise. (I
believe the premise merits a discussion of its own but I will
skip that for now.)
Saying that the width of bool must be 1 and is implementation-defined is
inconsistent.

If we accept the premise, that's right, but I don't think the DR
means to say that the width of a _Bool is -- in and of itself --
implementation-defined, only that it is a consequence of an
implementation-defined choice (namely, the representations of
different types).

In fact, the width and precision of all the integer types
are not explicitly implementation-defined, but only implicitly
so, because their representations are implementation-defined.

The representation of _Bool is implementation-defined (and
there is more than one possibility). The width of _Bool is a
consequence of this implementation-defined choice. Referring
to the "implementation-defined width" in the DR was just a
shorthand for the implications of an implementation-defined
representation, which the Standard does require, without
consideration of the consequences that other requirements in
the Standard might have on the set of choices available.
(Note that the DR did not result in an changes being made to
text in the Standard.)

Of course, it is possible that the committee actually wants to
allow the possibility of _Bool having a width greater than
one, but doing that would have to mean making a change to how
conversions work (or perhaps some other part of the Standard).
As far as I know, the Standard's current draft still imposes
the same constraints that restrict the width of _Bool to be
exactly one.
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
Keith Thompson said:
...
When I convert the value of u.b to _Bool (a conversion from
_Bool to _Bool)...

_Bool to _Bool does not require a conversion, a _Bool *is* a _Bool.

Assignment _always_ performs a conversion, even if the two types
are the same. 6.5.16.1p2 -- look it up.

Interesting.

So this:
int i;
i = 42;
performs a conversion from int to int (because 6.5.16.1p2 says so), but
this:
(int)42;
does not perform a conversion (I don't think that's explicitly stated,
but otherwise the last sentence of 6.5.4p4 would be meaningless).
[snip elaboration]

No, a cast always performs a conversion. 6.5.4p4:

Preceding an expression by a parenthesized type name
converts the value of the expression to the named type.
This construction is called a cast. A cast that specifies
no conversion has no effect on the type or value of an
expression.

The first sentence mandates that a conversion be performed,
with no exceptions.

The third sentence, it seems fairly clear, is talking about
cases where an expression is converted to an expression of
the same type. However, it does not say no conversion is
performed, only that a cast that /specifies/ "no conversion"
not change the type or value. The cast still must effect
a conversion, even if it "does nothing".

Casting an expression to the same type as the expression
must effect a conversion because (despite 6.5.4p4) such
conversions can have semantic consequences. See 6.3.1.5p2.

I think the standard is unintentionally inconsistent,

The actual text isn't really inconsistent. What I think you
mean is that it expresses (or might express) something different
from what was intended to be expressed.
and we're
trying to extract meaning from the particular way things are phrased.
I suggest that the end result of this analysis should be a set of
suggested changes to the standard, not necessarily any definitive
conclusion about what it "really means".

I agree the phrasing should be clarified. If something
needs to be changed, I think the first step is to identify
what requirements are actually desired.

In the case of (int)42, if the cast "specifies no conversion",
then what does? Why would a conversion be performed if nothing
specifies it?

It's probably just an unfortunate choice of wording. Most
likely what is meant is a cast to the same type (or a compatible
type?) as the type of the expression being casted. The Standard
generally avoids cumbersome phrases if it can; I suspect
"specifies no conversion" was seen as a good way to avoid the
cumbersome phrase about casting to the same type (and also is a
holdover from C90 when these questions didn't matter as much).

I think the intent is that the third sentence is talking about an
exception to the rule stated in the first. I grant that I'm not
on very firm ground with this interpretation, but it's what makes
the most sense to me (though it certainly could have been stated
more clearly).

I believe it's just a clarification, and at some level
unnecessary because it's implied by 6.3p2. Also, I
don't believe casting to the same type is intended to
be "no conversion", specifically because with floating
point types casting to the same type has (or can have)
semantic consequences.

C90 had very similar wording -- and in C90, there was no real
difference between not doing a conversion and doing a conversion
from a type to the same type. I suspect that the authors of the
standard didn't realize the introduction of semantically meaningful
_Bool-to-_Bool conversions called for the wording about conversions
and casts to be revisited.

You may be right but IMO speculations along such lines aren't
going to be helpful (or at least are hardly ever helpful). The
key questions are:

What do implementors (and developers) think the Standard requires?

What does the committee understand the requirements to be?

Is the existing text confusing or ambiguous? (I think at least
one of these must be "Yes".)

Does the existing text just need to be clarified, or does it
need to be changed? (Kind of a gray question, but the point
of it is to ask whether there are "new semantics", eg, are
wording changes required in paragraphs besides the ones in
the section on casting.)

If it just needs clarification, what phrasing would be better?
(eg, could the question be addressed just by adding a footnote?)

If it needs to be changed:
first, what behavior is meant to be required? and,
second, what phrasing will clearly express those requirements?
 
M

Michael Press

Kenneth Brody said:
(e-mail address removed) (Kenny McCormack) wrote: [...]
Remind me again: Just exactly how many angels can dance on the head of a pin?

In my calculation may I ignore the space taken by the orchestra?

Unless they are also dancing, yes.

That does not simplify things. A trombone takes up
a lot of room, and even more so when it is dancing.
 

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,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top