rwallace
rwallace

Reputation: 33395

Casting to _Bool

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

Answers (2)

Clifford
Clifford

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

Vlad from Moscow
Vlad from Moscow

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

Related Questions