James Van Buskirk said:
["Followup-To:" header set to comp.lang.c.]
Posted to clf because the nature of the question is central to an
issue due to Fortran interoperability (_Bool <-> LOGICAL(C_BOOL)).
At last! A C programmer to inflict the Question on! Now, what
if true is a const _Bool with internal representation B'00000010'
and var is also an _Bool. Does the assert happen if NDEBUG is
not on?
The code generated by the assert macro, when NDEBUG is not
present, should not treat this expression any differently than
something like
if (var = true) ...
The assignment must happen if NDEBUG is absent, and its result
tests as true.
Yes, this last line of code above is perhaps a better illustration
of the issue. My impression was that assignment between variables
of the same integer type in C was to copy all the bits, ...
Not quite - the value of the right operand of an assignment
expression is determined (a process that may involve the usual
arithmetic conversions), and is then converted to the destination
type (if different).
Part of the premise of this subthread is that both left and right
operands have the same intrinsic type, _Bool. See above. In
n1124.pdf, section 6.3 I read:
"Conversion of an operand value to a compatible type causes no
change to the value or the representation."
Doesn't that mean that the compiler is just supposed to copy bits?
[snip elaboration]
The short answer is no, but it's instructive to look at why.
First, if the width of _Bool is 1, then it may only ever store
the values 0 and 1. Any bit pattern occupying a _Bool object
will therefore denote either 0, or 1, or a trap representation.
If the bit pattern denotes a 0 value then 0 will be stored; if
the bit pattern denotes a 1 value then 1 will be stored; and if
the _Bool object holds a trap representation then any behavior at
all is permissible, either copying the bits, or storing a 0 or 1
value, or crashing the program. So a compiler is not obliged to
exactly copy the bits in this case, although of course it may,
but the key thing is it doesn't have to.
Now consider the question when the width of _Bool is greater
than 1. Under this assumption a _Bool may now hold an object
representation corresponding to the value 2 or 3 (and perhaps
others, but these are enough), and are legal values, ie, not
trap representations. The Standard imposes two requirements:
one, that conversion to the same type causes no change to the
value or representation; and two, that conversion to a _Bool
type produces 0 if the original value compares equal to 0, and 1
otherwise. The only way both of these requirements can be
satisfied simultaneously is if a _Bool object may not definedly
hold a value other than 0 or 1. Hence the possibility that the
width of a _Bool is greater than 1 is not satisfiable in a
conforming implementation. Therefore we may conclude that _Bool
/must/ have a width of 1, which gives each implementation enough
freedom to either just copy the bits or not, as it chooses.