52

Many compilers seem to be keeping only 0 or 1 in bool values, but I'm not sure this will always work:

int a = 2;
bool b = a;
int c = 3 + b; // 4 or 5?
Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
mojuba
  • 11,842
  • 9
  • 51
  • 72
  • 2
    For the C++ part, see [Can I assume (bool)true == (int)1 for any C++ compiler ? ](http://stackoverflow.com/questions/2725044/can-i-assume-booltrue-int1-for-any-c-compiler). For C, see [Is bool a native C type? ](http://stackoverflow.com/questions/1608318/is-bool-a-native-c-type). – Matthew Flaschen Nov 25 '10 at 11:20
  • 2
    I'm more interested in the question worded as "Is a boolean _expression_ always guaranteed to evaluate to 0 or 1?", to which the answer is unambiguously _yes_ – bobobobo Apr 29 '12 at 17:01
  • Related: http://stackoverflow.com/questions/5189072/c-bool-question – Palec Jan 19 '15 at 05:13
  • In newer C version, there is a standard bool type which has values 0 and 1 only, as in C++. Assignment converts non-zero to 1. – gnasher729 Apr 25 '16 at 07:41
  • Note that bool cast will make sure `b` is 1. But you can still make `b` into 2 using hacks like unions, memset, etc. – SOFe Jul 19 '18 at 08:28

6 Answers6

57

Yes:

In C++ (§4.5/4):

An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true becoming one.

In C, when a value is converted to _Bool, it becomes 0 or 1 (§6.3.1.2/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.

When converting to int, it's pretty straight-forward. int can hold 0 and 1, so there's no change in value (§6.3.1.3).

Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
  • 7
    Note that for C, it depends on the type `_Bool`. If you instead have `typedef enum { false, true } bool;` it does not work this way. – Chris Dodd Apr 23 '13 at 18:22
22

Well, not always...

const int n = 100;
bool b[n];
for (int i = 0; i < n; ++i)
{
    int x = b[i];
    if (x & ~1)
    {
        std::cout << x << ' ';
    }
}

Output on my system:

28 255 34 148 92 192 119 46 165 192 119 232 26 195 119 44 255 34 96 157 192 119
8 47 78 192 119 41 78 192 119 8 250 64 2 194 205 146 124 192 73 64 4 255 34 56 2
55 34 224 255 34 148 92 192 119 80 40 190 119 255 255 255 255 41 78 192 119 66 7
8 192 119 192 73 64 240 255 34 25 74 64 192 73 64

The reason for this apparently weird output is laid out in the standard, 3.9.1 §6:

Values of type bool are either true or false. Using a bool value in ways described by this International Standard as "undefined", such as by examining the value of an uninitialized automatic object, might cause it to behave as if it is neither true nor false.

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • 3
    @Sebastian: So uninitialized variables have defined behaviour? – CiscoIPPhone Nov 25 '10 at 11:40
  • 4
    @hha: Note the line `int x = b[i]`, I really expected this random stuff to be converted to either 0 or 1 here. Didn't you? – fredoverflow Nov 25 '10 at 11:47
  • 3
    no not really, the array is just a chunk of uninited memory it can have anything in it, if you had done bool b[n] = {0} then that's a different story. However your quote from the standard is informative so + 1 for pointing out the exception – hhafez Nov 25 '10 at 11:58
  • 4
    @Sebastian: Trying to access an uninitialized variable *is* UB. @FredOverflow: Did you? I didn't expect anything, it's UB after all. Do you really think there should be a conversion step each time a boolean value is accessed? There is no defined way to store anything but `true` or `false` to a boolean variable. – eq- Nov 25 '10 at 12:08
  • The standard should mention somewhere that an uninitialized bool isn't necessarily either true or false. It can be in some unspecified state. – visitor Nov 25 '10 at 13:07
  • @visitor: The standard says that any uninitialized memory location is in some unspecified state, so yes it does mention it somewhere – Fabio Fracassi Nov 25 '10 at 13:52
  • @visitor: in the case of C99 and the type `_Bool` the standard does as far as I remember. `_Bool` is an unsigned integer type and since it is represented in at least 8 bit, at least 7 of the bits are padding bits. "Values" of the variable that have other bits set may be so-called trap representations and accessing them leads to UB. – Jens Gustedt Nov 25 '10 at 14:15
  • @CiscoIPPhone I consider "undefined behavior" to be a technical term that means "the compiler can do whatever it wants with this statement and your program may terminate or not". In this sense, accessing uninitialized memory is clearly defined behavior. You can read it, and the data you read is random. Nothing else is *allowed* to happen. – Sebastian Nov 25 '10 at 14:50
  • 8
    @Sebastian: You are simply wrong. Other things, including terminating the program or `system("rm -rf /");` **are** allowed to happen if you access the value of uninitialized variables. – R.. GitHub STOP HELPING ICE Nov 25 '10 at 14:55
  • http://stackoverflow.com/questions/4279264/is-reading-an-indeterminate-value-undefined-behavior – Sebastian Nov 25 '10 at 16:48
  • @FredOverflow you are pointing out an interesting example that _does_ answer the question - really the value of allocated but not written to memory is going to be some random bytes. Your point is good given the way the question was worded. Argument because the question really should be "Is a boolean _expression_ always guaranteed to evaluate to 0 or 1?" – bobobobo Apr 29 '12 at 17:00
  • 1
    Undefined behaviour. No guarantees of the C++ or C standard apply with undefined behaviour. – gnasher729 Apr 25 '16 at 07:43
  • The passage misquoted in this answer doesn't define any undefined behaviour (it simply talks about undefined behaviour, as defined elsewhere in the standard) and doesn't have any bearing on the question. It says nothing at all about values other than "true" and "false" invoking undefined behaviour; quite the reverse. The accurate quote is: "Using a bool value in ways described by this International Standard as “undefined,” such as by examining the value of an uninitialized automatic object, might cause it to behave as if it is neither true nor false." – Buster Oct 28 '16 at 22:35
19

Is C/C++ .......

There's no language named C/C++.

bool type always guaranteed to be 0 or 1 when typecast'ed to int?

In C++ yes because section $4.5/4 says

An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true becoming one.

.

int c = 3 + b; // 4 or 5?

The value of c will be 4

Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
  • 2
    except in C, C doesn't even have a bool type :) – hhafez Nov 25 '10 at 10:57
  • 2
    @hhafez : In C, until C99, there was no bool datatype. Kindly lift your downvote. – Prasoon Saurav Nov 25 '10 at 11:03
  • 6
    C99 defined a new type `_Bool` and a typedef `bool` in the header ``. If you do not `#include `, your programs cannot use `bool`, but they can use `_Bool`. – pmg Nov 25 '10 at 11:27
  • 45
    -1 for pointing out that there is no language called C/C++. The remark is pedantically correct, but deliberately unhelpful. It is not as though the original poster had referred to, say, C/SQL. If you know the C++ but not the C standard, just say so. – thb Nov 15 '14 at 13:10
  • 6
    @thb I disagree that the remark is unhelpful. The idea that C++ is C with more features is quite widespread. The standards of the two languages differ in many ways and this is an important consideration. – martinkunev Dec 22 '19 at 16:33
10

One more example when you are out of the safe boat:

  bool b = false;
  *(reinterpret_cast<char*>(&b)) = 0xFF;
  int from_bool = b;
  cout << from_bool << " is " << (b ? "true" : "false");

Output (g++ (GCC) 4.4.7):

  255 is true

To be added to the FredOverflow's example.

Community
  • 1
  • 1
Alex Che
  • 6,659
  • 4
  • 44
  • 53
3

There is no bool type in C pre C99 (Such as C90), however the bool type in C99/C++ is always guaranteed to be 0 or 1.

In C, all boolean operation are guaranteed to return either 0 or 1, whether the bool type is defined or not.

So a && b or !a or a || b will always return 0 or 1 in C or C++ regardless of the type of a and b.

MSalters
  • 173,980
  • 10
  • 155
  • 350
hhafez
  • 38,949
  • 39
  • 113
  • 143
  • 4
    C does have `bool`. Technically, the type is `_Bool`, and `bool` is a macro, but that usually doesn't matter unless you're using a conflicting library. – Matthew Flaschen Nov 25 '10 at 10:59
  • @hhafez: Standardized boolean type (_Bool) in C is older than languages like C#. Not too much experience with C, after all? – eq- Nov 25 '10 at 11:07
  • what does C have to do with C# I don't understand your comment – hhafez Nov 25 '10 at 11:09
1

Types with padding bits may behave strangely if the padding bits don't hold the values expected for the type. Most C89 implementations didn't use padding bits with any of their integer types, but C99 requires that implementations define such a type: _Bool. Reading a _Bool when all of its bits are zero will yield zero. Writing any non-zero value to a _Bool will set its bits to some pattern which will yield 1 when read. Writing zero will set the bits to a pattern (which may or may not be all-bits-zero) which will yield 0 when read.

Unless specified otherwise in an implementation's documentation, any bit pattern other than all-bits-zero which could not have been produced by storing a zero or non-zero value to a _Bool is a trap representation; the Standard says nothing about what will happen if an attempt is made to read such a value. Given, e.g.

union boolChar { _Bool b; unsigned char c; } bc;

storing zero to bc.c and reading bc.b will yield zero. Storing zero or one to bc.b will set bc.c to values which, if written, will cause bc.b to hold zero or one. Storing any other value to bc.c and reading bc.b will yield Undefined Behavior.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • I concur that the representation of `_Bool` is required to have padding bits, but I'm not seeing a basis for the assertion that "Any bit pattern other than all-bits-zero which could not have been produced by storing a 0 or 1 to a `_Bool` is a trap representation". It is explicitly possible that `_Bool` or any other integer type with padding bits affords trap representations, but the standard does not *require* that or any other particular interpretation of the padding, nor does it require that there be a unique valid representation for every value supported by a given type. – John Bollinger Nov 09 '18 at 18:28
  • @JohnBollinger: The Standard imposes no requirements with regard to how implementations process any bit patterns for which they would not be required to assign a meaning. Implementations may document how they will process reads of such patterns, but they can also document any other action which, from the point of view of the Standard, invokes Undefined Behavior. – supercat Nov 09 '18 at 18:43
  • That is more or less my point, @supercat. The fact that the standard (indirectly) requires the representation of type `_Bool` to have padding bits does not imply that that type must afford any trap representations, nor are any specific bit patterns meeting the criteria you present required to be trap representations. The standard does not limit valid representations to those that can be stored as a side effect of an assignment expression. – John Bollinger Nov 09 '18 at 19:04
  • @JohnBollinger: From the point of view of the Standard, what is a trap representation if not "an object representation that need not represent a value of the object type", i.e. a bit pattern to which implementations are not *required* to attach a meaning? Implementations are allowed to attach meanings to bit patterns beyond those required by the Standard, but the fact that an implementation happens to document the meaning of a bit pattern would not prevent it from being an "object representation that need not specify a value of the object type". – supercat Nov 09 '18 at 19:51
  • You are interpreting the definition of *trap representation* more broadly than I think is intended or warranted. Consider the standard's provision that for sign-value integers, it is implementation-defined whether the representation having sign bit 1 and all other bits 0 is a trap representation. As far as the standard is concerned, that pattern need not represent a value, but it also is not necessarily a trap representation. The "need not represent a value" wording is a bit wrought, I think, but it should be interpreted from the perspective of the implementation. – John Bollinger Nov 09 '18 at 20:26
  • To go at the overall issue from the other direction, however, the standard allows assigning values different from 0 and 1 to objects of type `_Bool`. It requires the resulting `_Bool` value to compare equal to either 0 or 1, but it does not limit resulting representations to those arising from assigning 0 or 1, nor does it even require the representation arising from assigning 0 to be all-bits-zero. Your claim, then, seems not to be supported by the standard under even your own interpretation of "trap representation". – John Bollinger Nov 09 '18 at 20:35
  • @JohnBollinger: The Standard requires that all-bits-zero be a valid representation of zero for all integer types, and I don't think `_Bool` is exempt from that. You are correct that an implementation could decide to use a bit pattern for storing "2" that it would never use when storing "1", provided that reading the object would yield "1" in any case. – supercat Nov 09 '18 at 20:57
  • @JohnBollinger: Do you think the above edit is better? – supercat Nov 09 '18 at 20:59
  • Yes, all-bits-zero is definitely a representation of zero. But it doesn't have to be the *only* representation of zero, and if there is more than one then all-bits-zero doesn't have to be the representation produced when the value zero is assigned to a `_Bool`. As for the edit, I do like the new text better. I think it's still too restrictive, but there's more room for interpretation there. – John Bollinger Nov 09 '18 at 21:07
  • @JohnBollinger: I did expressly note that the bit pattern resulting from storing zero need not be all bits zero, and regarded all bits zero as distinct from the bit patterns produced by storing zero or non-zero values. – supercat Nov 09 '18 at 21:09
  • Acknowledged, and again, I do like the updated text better. Thank you. – John Bollinger Nov 09 '18 at 21:13