3

In C (before C99), booleans are usually represented as

typedef int bool;
#define true 1
#define false 0

Why it is represented as 'int' rather than 'float'?

This is an interview question, even I wonder why such question is asked! Any convincing answers?

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
Shri
  • 1,223
  • 5
  • 22
  • 31
  • 3
    float size's bigger than int ... – Ta Duy Anh Oct 22 '12 at 10:54
  • 8
    Why would you *want* it to be represented as a float? Floating point operations are slower, and it's completely pointless to use floating point for a type that has only two values. – jamesdlin Oct 22 '12 at 10:55
  • on most machines, `float`s are the same size as `int`s – K. Brafford Oct 22 '12 at 10:56
  • 1
    @Taiki: At least in x86 and ARM, `sizeof(float)` = `sizeof(int)` = 4. – kennytm Oct 22 '12 at 10:56
  • 3
    "Most machines" now, but to be fair back in the 70s or 80s when the convention was established, `sizeof(float) == 4; sizeof(int) == 2;` was common. In addition all the other reasons why `int` is preferable to `float`, that's not a bad one, but it doesn't explain why not to use `char`. – Steve Jessop Oct 22 '12 at 12:20
  • All relational operators yield a signed int with the value 0 or 1 as their result. A bool type of int with those value would be directly compatible with it. – Kenneth Feb 19 '15 at 08:16

4 Answers4

6

bool values are mostly used in comparisons, and using the int type uses the integer ALU for these comparisons. It is very fast, as it's in the CPU's normal pipeline. If you were to use the float type, then it would have to use the floating-point unit, which would take more cycles.

Also, if you wanted to support using your bool type in mathematical expressions, i.e.:

x = (4 * !!bool1) + (2 * !bool1);

so as to avoid unnecessary branching, your use of the integer ALU would also be faster than using the floating point unit.

The above code is equivalent to the following branching code:

if (bool1) {
   x = 4;
} else {
   x = 2;
}
K. Brafford
  • 3,755
  • 2
  • 26
  • 30
  • 1
    I'd suggest replacing `(4 * bool)` with `(4 * !!bool)`. Hopefully you know why. – Brendan Oct 22 '12 at 11:15
  • This was the case in older processors, modern processors dont have different units – Manik Sidana Oct 22 '12 at 11:20
  • With the x86, you still have to push two args onto the fpu stack then issue the `fcomi` instruction: http://stackoverflow.com/a/7057771/33263 – K. Brafford Oct 22 '12 at 11:23
  • @Brendan, I think I used to know why, but am drawing a blank now. Is it a preprocessor substitution issue? – K. Brafford Oct 22 '12 at 11:25
  • 1
    @K.Brafford if `bool` is an integer type, that implies `4 * bool1` can overflow if `bool1` is true, resulting in undefined behaviour. – Michael Foukarakis Oct 22 '12 at 11:32
  • 2
    That said, if `bool` is an integer type whose value is either 0 or 1, because it's only ever assigned from the result of a logical expression, then no overflow is possible. So it depends on the source of your values. Adding `!!` does additional work to validate input. Everyone probably has a different view exactly when such work can/should be removed for optimization purposes, but *if* you're writing clever code to avoid branches, *and* you trust the source of the value, then I'd say leave it out. – Steve Jessop Oct 22 '12 at 12:26
  • @all this seems to be more close answer, however if int goes easy on processor, why not use char which is both an integer itself but it will take lesser space? – Shri Oct 22 '12 at 13:10
  • (Your question is novel because the interviewer threw in the "why not float" twist) – K. Brafford Oct 22 '12 at 13:25
  • @K.Brafford Yeah! may be you are right! However I am accepting this answer as whole(including all discussion in comment section) – Shri Oct 23 '12 at 08:42
2

There are many many reasons why this would be a bad idea. But the reason why it was not done, ie the historical reason why it was not done that way is, that early computers did not have a floating point unit (and for an even longer period of time some had one and some did not).

Bernd Elkemann
  • 23,242
  • 4
  • 37
  • 66
1

C's _Bool/bool (and C++'s bool) is supposed to be a very simple numerical type and behave as one and you cannot get any simpler than something like char or int.

int is a typical choice for performance or historical reasons.

Substituting float would limit it. You won't be able to shift a float with << and >>.

You sometimes want to be able to shift the result of the operators like &&, ||, ==, !=, >, <, >=, <=, !, which is of type bool in C++ and _Bool/bool in disguise in C (implicitly converted into int).

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
  • 1
    What will you achieve by shifting bools.I cannot think of a case where shifting of bools is done or required – Manik Sidana Oct 22 '12 at 11:19
  • @ManikSidana Then you haven't coded enough or haven't seen enough of other people's code. Say, you want to set bit 3 in `int x` on some condition, say, if `y<0` and reset it otherwise. You can do it like this: `x |= (y<0)<<3`. – Alexey Frunze Oct 22 '12 at 11:23
  • 1
    Well!!! Dont arrive at conclusion so quickly. I said I havnt seen << >> in "BOOLS". On integers, it is widely done.... Read again – Manik Sidana Oct 22 '12 at 11:25
  • 1
    @ManikSidana: if you want to see it with bools then it's a very simple change to Alexey's code. `bool condition = (y < 0); x |= (condition << 3);`. Are you now happy that there is a case where shifting bools is "done or required", and so it's useful that `condition` is an `int` underneath? – Steve Jessop Oct 22 '12 at 12:18
  • @AlexeyFrunze: the result of the logic operators in C actually is `int` isn't it, not `_Bool` implicitly converted? – Steve Jessop Oct 22 '12 at 12:30
  • @SteveJessop Yes, but it can be done via `_Bool` underneath and for most practical uses you wouldn't notice the difference between `_Bool` and `int`, perhaps `sizeof()` could tell the difference on some platforms. – Alexey Frunze Oct 22 '12 at 12:38
  • @Alexey: sure, it makes no difference in contexts where the result is subject to promotion, which is "normally". At least, in saying that I assume `_Bool` isn't allowed to be *bigger* than `int`. I haven't actually checked, but if not then there might be cases where it's subject to promotion but still somehow makes a difference. – Steve Jessop Oct 22 '12 at 12:44
  • I should be able to change the definition of `bool` so that true==0 and false==1 and expect code using `bool` still to work. But any code that assumes true==1 will break. Shifting bools is only any use if you assume that true==1. Conclusion: shifting bools is logically incorrect. Just because you have seen it done does not make it right. – William Morris Oct 22 '12 at 13:24
  • 1
    @WilliamMorris Let's agree to disagree. – Alexey Frunze Oct 22 '12 at 13:32
  • 1
    @Steve Jessop: If you want to be obstinate about it, then I say agreed.... I just stated a simple point, lets not turn it into an argument.... – Manik Sidana Oct 22 '12 at 14:23
  • 1
    @SteveJessop 6.3.1.1 "The rank of _Bool shall be less than the rank of all other standard integer types.", and ibid. (2) "An object or expression with an integer type (other than int or unsigned int) whose integer conversion rank is less than or equal to the rank of int and unsigned int.", a `_Bool` is always promoted to an `int` where integer promotions take place (as they do for shifts). Now, `_Bool` may have padding bits, so `sizeof(_Bool) > sizeof(int)` isn't forbidden by the standard, but that's irrelevant for the promotions. – Daniel Fischer Oct 22 '12 at 15:41
  • 1
    @WilliamMorris: "I should be able to change the definition of bool so that true==0 and false==1 and expect code using bool still to work". The C standard disagrees. In C99, `true` is stated to convert to 1, but even in C89 if you want your `bool` type to be consistent with the results of logical operators (so that for example `(1 == 1) != false`), then you can't define `false` to be 1. If you desire a `bool` type that doesn't need to be consistent with the results of logical operations, well, you're in an irrelevant minority ;-p – Steve Jessop Oct 22 '12 at 15:45
  • @SteveJessop: Mmmm, I always thought what I said to be true, but it is clear now that I was wrong - thanks! But I still think shifting a variable *declared* `bool` is logically wrong. I'm not sure this applies to the example given above, `x |= (y<0)<<3;` - is `(y<0)` really a considered to be a `bool` or is it an `int`, the results of a logical operation, that just happens to have the value 1 (which happens to be the same as `true`)? I don't know the answer to that. – William Morris Oct 22 '12 at 21:09
  • Looking in the C99 standard, the result of comparisons such as `(y<0)` is `int` (6.5.8para6) so the shift in the above operation is not acting on a `bool`. (Actually, on writing this, I just noticed that SteveJessop said this in the 5th comment above...) – William Morris Oct 24 '12 at 00:38
1

With many reasons mentioned by other answers (slow, historical, etc.) I want to add that typically floating point numbers have 'Accuracy' problem (Ref: Wikipedia). Who wants all of these problems to make computer say the 'Truth' or 'Falsehood'? I hope you wouldn't want either. And it's pointless to choose something which is 'NOT ACCURATE' for being used as 'boolean' value.

Ayub
  • 989
  • 10
  • 12
  • 1
    This is completely irrelevant. First, floating point is perfectly capable of representing 0 and 1 exactly. Unless you intend to be taking the cosine of true, the rounding that occurs in floating-point operations is irrelevant. Second, integers suffer the same issues. For example, if you divide 7 by 3, the result is mathematically incorrect (it is 2 but should be 2 1/3). This does not matter when using integers to represent Boolean values because you do not divide true by 3 or do other inaccurate operations. The same is true for floating point. – Eric Postpischil Oct 22 '12 at 13:49
  • Ok, we already know that 'int' should be the type for 'boolean'. But we are finding reasons why 'float' might not be used. There may be a hypothetical reason as well. But for accuracy we can guarantee that the integer arithmetic will give us 'exact' result (as we know 7/3=2 for int). But for floating point you won't get any 'exact' value in many cases. For example, floating point introduces precision which may make us take a 'round up' value. I am not arguing, I am showing various dark sides of choosing floats for boolean. – Ayub Oct 22 '12 at 15:54
  • Precision does not affect using floating point for Boolean. It is simply irrelevant. Using 0 and 1 for false and true will work in floating point without any errors. None of the floating-point operations you perform on them to implement Boolean operations will produce any inaccuracies. Tests for equality or inequality will work properly. There is simply no effect from precision, so it is irrelevant. Integers have precision too. Integer operations are also imprecise in some operations. But this does not prevent them from being used for Booleans. The same is true for floating point. – Eric Postpischil Oct 22 '12 at 16:02
  • Ok, if you say that '0' and '1' is going to be used as '0' and '1' always then any type would be suitable. But in C you may want to do many things with the boolean result (which may include any arithmetic operations) and as the result you may come up with a 'non-exact/approximate' value due to floating point round-up thing. I accept your answer for all 'best cases' (or even good cases) of floating point arithmetic. – Ayub Oct 22 '12 at 16:08