Reputation: 33395
Traditionally, Boolean values in C were represented with int
or char
. The new _Bool
type makes intent clearer, but also has another interesting feature: it seems casting floating-point numbers to it, does not truncate toward zero, but compares with exact zero:
#include <stdio.h>
int main(int argc, char **argv) {
double a = 0.1;
int i = (int)a;
printf("%d\n", i);
_Bool b = (_Bool)a;
printf("%d\n", b);
return 0;
}
prints
0
1
So this is a semantic difference. And one I'm happy with; it duplicates the effect of using a floating-point number as a conditional.
Is this something that can be depended on across-the-board? Does the new C standard define the result of casting X to _Bool
as identical to X ? 1 : 0
for all X for which that is a valid operation?
Upvotes: 4
Views: 126
Reputation: 93476
It is entirely consistent, a non-zero value implicitly cast to _Bool
is true
. Since _Bool
is a true Boolean type and not "faked", it can behave correctly. So:
_Bool b = (_Bool)a ;
is equivalent to:
_Bool b = (a == 0) ;
not:
_Bool b = ((int)a == 0) ;
In the end interpreting a float as Boolean is nonsense and ill-advised as is comparing it for equality to zero. If you want the semantic you expect, you must code it explicitly:
_Bool b = (_Bool)((int)a);
Semantically that is equivalent to :
_Bool b = (a < 1.0);
It is clearer and safer to use a Boolean expression than to force a value to Boolean with a cast.
Upvotes: 1
Reputation: 311018
In the C Standard (6.3.1.2 Boolean type) there is written
1 When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1.
That is during conversion to the type _Bool
the compiler does not try to represent the value (truncating toward zero or something else) of the operand of an expression with the casting operator as an integer. It only checks whether the value is equal or unequal to zero.
Actually this declaration
_Bool b = (_Bool)a;
is equivalent to
_Bool b = a;
Upvotes: 5