5

Consider the code

bool f() { return 42; }

if (f() == 1)
    printf("hello");

Does C (C99+ with stdbool.h) and C++ standards guarantee that "hello" will printed? Does

bool a = x;

is always equivalent to

bool a = x ? 1 : 0;
  • I'm sure this question is a duplicate, but *A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one*. – chris Mar 19 '14 at 18:21
  • 2
    Why you do such comparison? – xis Mar 19 '14 at 18:24
  • Exactly what Xiaoge Su said: Why do you even care? Such code is never as expressive as explicitly writing `false` or `true`. – stefan Mar 19 '14 at 18:26
  • @XiaogeSu: I code for MCU and often my booleans are logic levels, e.g. `if (gpio_read(jumper) == 1) gpio_write(led, 1);`. It is more readable than simply `if (gpio_read(jumper))` or with `== true`. –  Mar 19 '14 at 18:26
  • 2
    I would have thought you would have printed "The meaning of life." instead of "hello" :) – Engineer2021 Mar 19 '14 at 18:27
  • the only boolean that I can see is the one generated by the implicit cast according to the return type of your function `f`, this is a really cumbersome way of expressing yourself. Try to write this in a much simpler manner. – user2485710 Mar 19 '14 at 18:29
  • @Corvus I believe in C/C++, `0` in `if` is always `false`, while non-`0` in `if`, including `1`, `-1`, etc. is always `true`. – xis Mar 19 '14 at 18:37
  • @XiaogeSu: it's obviously right. My doubts was about implicit conversion 42 to 1. –  Mar 19 '14 at 18:41
  • @Corvus if you `return 42;` while your function type is `bool()`, then this is the same to `return true;' – xis Mar 19 '14 at 18:43
  • This question may be a duplicate and it may not be. The earlier question was poorly posed, so it is hard to tell. This question is better. – thb Nov 15 '14 at 13:19

4 Answers4

3

Yes. You are missing a step though. "0" is false and every other int is true, but f() always returns true ("1"). It doesn't return 42, the casting occurs in "return 42;".

lgvidal
  • 329
  • 2
  • 10
  • Thanks. My doubts are from old times when I write in C without boolean type, just using the hack `typedef unsigned char bool`. In this case "hello" from my code will not printed. –  Mar 19 '14 at 18:31
3

In C macro bool (we are speaking about the macro defined in stdbool.h) expands to _Bool that has only two values 0 and 1.

In C++ the value of f() in expression f() == 1 is implicitly converted to int 1 according to the integral promotion.

So in my opinion this code

bool f() { return 42; }

if (f() == 1)
    printf("hello");

is safe.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • C has `bool`?? Since when? I'm behind on the times I guess.. AFAIK, `BOOL` is anything > 0 and `FALSE` is 0? Similar to WinAPI's `BOOL` which is defined as `INT` and can be anything that isn't 0.. yes? I don't know I guess.. I usually see `typedef enum boolean{false, true};` – Brandon Mar 19 '14 at 18:28
  • 1
    @CantChooseUsernames We are speaking about the macro bool defined in stdbool.h – Vlad from Moscow Mar 19 '14 at 18:30
  • Ohh.. well +1 from me anyway. Didn't know it had that. – Brandon Mar 19 '14 at 18:32
  • @CantChooseUsernames: C has built-in boolean type since 1999. –  Mar 19 '14 at 18:39
  • @Corvus In fact it s not a boolean type. It is an integral type with the domain of two values.:) – Vlad from Moscow Mar 19 '14 at 18:41
  • @VladfromMoscow: Привет, Влад. What is the difference between "boolean" and "integer with two values"? –  Mar 19 '14 at 18:43
  • @Corvus It is a good question. I did not check but it seems that in C you should explicitly convert function pointer to _Bool for example in an assignment statement _Bool b = f;. In C++ such a conversion can be implicit. In such languages as C# and Java bool is not an integral type. – Vlad from Moscow Mar 19 '14 at 18:58
  • http://ideone.com/izn7u7 bool can only hold 1 and 0 I think. Int can hold a variety of ranges. Some languages have bool strongly typed. Pascal is one where bool cannot be implicitly converted to int. – Brandon Mar 19 '14 at 19:00
2

In C++, bool is a built-in type. Conversions from any type to bool always yield false (0) or true (1).

Prior to the 1999 ISO C standard, C did not have a built-in Boolean type. It was (and still is) common for programmers to define their own Boolean types, for example:

typedef int BOOL;
#define FALSE 0
#define TRUE 1

or

typedef enum { false, true } bool;

Any such type is at least 1 byte in size, and can store values other than 0 or 1, so equality comparisons to 0 or 1 are potentially unsafe.

C99 added a built-in type _Bool, with conversion semantics similar to those for bool in C++; it can also be referred to as bool if you have #include <stdbool.h>.

In either C or C++, code whose behavior is undefined can potentially store a value other than 0 or 1 in a bool object. For example, this:

bool b;
*(char*)&b = 2;

will (probably) store the value 2 in b, but a C++ compiler may assume that its value is either 0 or 1; a comparison like b == 0 or b == true may either succeed or fail.

My advice:

  • Don't write code that stores strange values in bool objects.
  • Don't compare bool values for equality or inequality to 0, 1, false, or true.

In your example:

bool f() { return 42; }

Assuming this is either C++ or C with <stdbool.h>, this function will return true or, equivalently, 1, since the conversion of 42 to bool yields 1.

if (f() == 1)
    printf("hello");

Since you haven't constructed any strange bool values, this is well behaved and will print "hello".

But there's no point in making the comparison explicitly. f() is already of type bool, so it's already usable as a condition. You can (and probably should) just write:

if (f())
    printf("hello");

Writing f() == 1 is no more helpful than writing (f() == 1) == 1).

In a real program, presumably you'll have given your function a meaningful name that makes it clear that its value represents a condition:

if (greeting_required())
    printf("hello");
Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • @Corvus: I strongly disagree that `== 1` makes the condition more readable. I find `if (greeting_required())` much more readable than `if (greeting_required() == 1)` -- and the former is correct even if the function returns `int`. No, the standard doesn't protect against `*(char*)b = 2`. – Keith Thompson Mar 19 '14 at 18:56
0

The only real trick that I know of, that is useful with pre-C99 environments is the double negation

int a = 42;
if ( (!!a) != 0 ) printf("Hello\n");

this will print Hello because the result of the !! operation is a boolean that is true when the value is non-zero, false otherwise. But this is gonna cost you 2 negation to get the boolean that you want, in modern standards this is redundant because you will get the same result without the !! and it's a result granted by the language.

user2485710
  • 9,451
  • 13
  • 58
  • 102