36

The question is not so obvious as it seems, and I have trouble finding much information about the bool type in the standard.

According to the C++11 standard, what are the guarantees associated with the bool type with regards to:

  • Storage: how much space does it take, ignoring alignment? Is there any requirement for the value that will be stored to represent trueand false?
  • Values taken: Let b be of type bool, does the assertion (b == true) || (b == false) hold? Is (false < true) well-formed, and does it hold?
Adam Peck
  • 6,930
  • 3
  • 23
  • 27
Laurent LA RIZZA
  • 2,905
  • 1
  • 23
  • 41
  • my first guess would be - possible values true / false and is implicitly convertible from int (with 0 being false, non-zero being true). But I'm not sure about the implicit conversion to int. – Tobias Langner Sep 24 '13 at 14:52
  • http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf could be useful. – Aleph Sep 24 '13 at 14:59
  • @AnotherTest: Thank you, I've looked through the standard already ;) – Laurent LA RIZZA Sep 24 '13 at 15:03
  • @BradTilley: Usually, no. A byte is defined as the smallest addressable unit of memory, and all objects must be addressable. There are exceptions, such as bitfields, which are not addressable objects. – Mike Seymour Sep 24 '13 at 15:03
  • @BradTilley: OK. Consider that a rhetorical answer, then. – Mike Seymour Sep 24 '13 at 15:18
  • 17
    Just for fun: The **classical** values are `true`, `false` and obviously `file not found`. See http://thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx ;) – Daniel Frey Sep 24 '13 at 15:18
  • @DanielFrey : Thank you :) But since it's an `enum`, it can actually take any value storable by its underlying type. – Laurent LA RIZZA Sep 24 '13 at 15:25
  • @LaurentLARIZZA It's sad that you find stuff like that in the wild where someone doesn't even intended to make a joke. Another fun fact (before I finally shut up): The `enum` assigns `0` to `True`, which is `false` if you convert it to a real `bool`. Last sad fact: I've personally seen *even worse* ideas... 8-/ – Daniel Frey Sep 24 '13 at 15:28
  • 8
    @Daniel this one is a classic: http://msdn.microsoft.com/en-us/library/office/aa432714%28v=office.12%29.aspx – R. Martinho Fernandes Sep 24 '13 at 15:39
  • @DanielFrey is that only for `enum` , but not `enum class` [Asking since he tagged it c++11] – ninMonkey Sep 24 '13 at 21:08
  • @R.MartinhoFernandes OMG! I know I shouldn't be surprised, but still... thanks for sharing this one :) – Daniel Frey Sep 24 '13 at 21:12

5 Answers5

43

bool types are described in section §3.9.1, Fundamental types. Of relevance here is a sentence from paragraph 6:

Values of type bool are either true or false.47

The reference footnote 47 provides some interesting additional information:

47) 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.

This is just a direct consequence of the standard imposing no requirements on programs with undefined behaviour.

There are no size requirements on bool, other than the implicit "at least one byte" that applies to all types as a consequence of the C++ memory model.

There are also no requirements on the internal representation of bool objects, however, due to the requirements regarding integral conversions (true must convert to 1 and false to 0), implementations may be inclined to pick the same representations for true and 1, and for false and 0, since that makes such conversions unnecessary.

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • And with regards to how the value is stored, is there anything relevant? – Laurent LA RIZZA Sep 24 '13 at 14:54
  • @LaurentLARIZZA The size and object representation of a `bool` is implementation-defined. – Simple Sep 24 '13 at 14:57
  • No. The implementation is free to pick whatever representation it wants. – R. Martinho Fernandes Sep 24 '13 at 14:57
  • 1
    3.9.1 - 7: Values of type bool, char, wchar_t, and signed & unsigned integer types are collecitvely called integral types. The representation of integral types shall define values by use of pure binary numeration system. This basically means that bool is internally an integer number. I don't think that there's a strict number of bits defined for it. – Tobias Langner Sep 24 '13 at 15:00
  • @TobiasLangner: `sizeof(bool)` must be well formed, so it can't be less than 1 obviously. – Laurent LA RIZZA Sep 24 '13 at 15:01
  • sizeof does not give the size in bits, but bytes. Bytes must be at least 8-bit large. – R. Martinho Fernandes Sep 24 '13 at 15:02
  • @R.MartinhoFernandes : That's what I meant (can't be less than 1 byte, so can't be less than CHAR_BIT bits) :) Two more questions that I'll add: Is `(false < true)` well-formed, and does it hold? – Laurent LA RIZZA Sep 24 '13 at 15:06
  • @Laurent yes, through the aforementioned integral conversions (since you're interested, reference for those is §4.7). op< is defined in §5.something :) – R. Martinho Fernandes Sep 24 '13 at 15:10
  • @LaurentLARIZZA: Why do you think it matters? The implementation will do as needed to make correct programs work. It could store N bits all set to 0 or 1 (some implementations do) or it could store all 0s except the lowest bit being set or not depending on the value. Except when undefined behavior is involved, you cannot access the actual value. Conversions from `bool` to `int` guarantee that the value is either 0 or 1, regardless of how `bool` is internally represented – David Rodríguez - dribeas Sep 24 '13 at 15:11
  • @DavidRodríguez-dribeas: It's actually a philosophical question. I am trying to understand what it means for `bool` to be such a singular type that it has only 2 expressable values `true` and `false` in the language, while occupying storage space for so many more. `nullptr_t` is such another type. (only one expressable value) – Laurent LA RIZZA Sep 24 '13 at 15:19
  • 1
    @Laurent Paragraph 4 at §3.9 might help. Contrary to popular belief, most of the language is not built upon bits and bytes but upon objects and values, which are an abstraction of the bits and bytes. – R. Martinho Fernandes Sep 24 '13 at 15:27
  • @R.MartinhoFernandes: "Bytes must be at least 8-bit large" There are CPUs/chips that have non-8-bit bytes. – SigTerm Sep 24 '13 at 15:27
  • 2
    @SigTerm it doesn't really matter. If they are smaller than 8 bits, C++ cannot be implemented directly with the bytes native to the machine, and pretty much everything needs to emulated on such machines. – R. Martinho Fernandes Sep 24 '13 at 15:30
  • @LaurentLARIZZA: It only means that whatever representation it has, it needs to be able to hold at least 2 values (in the case of `bool`) or a singular value in the case of `nullptr_t`. The singular value is the simplest one to reason about: since values are only comparable through the given operators, you could implement your own type somehow similar to `nullptr_t` by overloading `operator==` to always return `true`, and `template operator T*() { return 0; }` for the conversion. For `bool` you could mimic it by storing N bytes and marking with two patterns for `true` and `false`. – David Rodríguez - dribeas Sep 24 '13 at 15:33
  • The C++11 standard specifies that the object model is supposed to be compatible with C99. C99 has the concept of value bits and padding bits, where padding bits are included in `sizeof(T)` but have no effect on the value of the object. You could think of `bool` as a type with only 1 value bit and the rest being padding bits. – Simple Sep 24 '13 at 15:42
  • @DavidRodríguez-dribeas: "For bool you could mimic it by storing N bytes and marking with two patterns for true and false" Apparently, there is nothing said in the Standard about the storage of bool. You could "mimic" it, but you could not user-define `bool`with the same freedom left to `bool`. Or could you? – Laurent LA RIZZA Sep 24 '13 at 15:43
  • @Simple: could you quote the Standard on that one? – Laurent LA RIZZA Sep 24 '13 at 15:44
  • @LaurentLARIZZA: No, you cannot implement `bool` as a user type, but you are asking about how it *could* be implemented. Replace *you* with *the implementation* in the above comment if you feel better with that. – David Rodríguez - dribeas Sep 24 '13 at 15:46
  • @Laurent see footnote in paragraph 4 at §3.9, that I mentioned above. – R. Martinho Fernandes Sep 24 '13 at 15:47
  • @DavidRodríguez-dribeas: No, I was not asking :) I just said that it was a philosphical question. The hidden questions are these: Is there any way of implementing a specialization of `std::optional` that takes only one byte of storage? What about `optional>`, and so on? If it's not possible, what is exactly missing to C++ so you can express it? – Laurent LA RIZZA Sep 24 '13 at 15:58
  • @DavidRodríguez-dribeas: "No, you cannot implement bool as a user type" Could you elaborate on that? boost has `tribool`. – SigTerm Sep 24 '13 at 15:58
  • @LaurentLARIZZA: What did you mean when you said "with the same freedom"? As far as I can see, you could use enum or a class with bunch of conversion/comparison operators. So, what's missing? – SigTerm Sep 24 '13 at 16:03
  • 2
    @SigTerm: You can implement something *similar* to `bool` but not `bool`. In particular, conversions from and to your type (say to `int`) will be *user-defined* conversions and not *integral promotions*, and there can be at most one implicit user defined conversion in any valid conversion sequence. You cannot substitute all uses of `bool` with `Bool` as some of them will fail to compile. – David Rodríguez - dribeas Sep 24 '13 at 16:04
  • @LaurentLARIZZA: That is the issue when you don't ask about your problem but rather about something else. If your question is whether `optional` can be optimized so that `sizeof(optional)==1`, the answer is trivially yes. Consider for example, `std::vector` which is an specialization of the container for a more compact representation [it has issues in that it does not comply with all the requirements of containers, but those would not apply to `optional`]. – David Rodríguez - dribeas Sep 24 '13 at 16:07
  • @DavidRodríguez-dribeas: " user-defined conversions and not integral promotions" Oh. Makes sense. – SigTerm Sep 24 '13 at 16:08
  • @DavidRodríguez-dribeas: That's not a trivial question. How many specializations do you have to define so that arbitratily many nested levels of `optional>>>` occupy a single byte? – Laurent LA RIZZA Sep 24 '13 at 16:12
  • 4
    @David I think you cannot implement optional in one byte in a way that works on all theoretical implementations if you want to provide `T& operator*();`. A pathological implementation could assume *all* available bit patterns represent one of true and false, and every time you write `x = true;` randomly pick one of the `true` patterns. That leaves you no stable pattern to represent your additional "none" state. Since you need to provide a reference to the object with operator*, you need to have a `bool` there somewhere. Note that vector works around this with those dreaded proxies. – R. Martinho Fernandes Sep 24 '13 at 16:12
  • @R.MartinhoFernandes: I was not aware of the pointer-like semantics of `std::optional`. Good point, that particular member won't work – David Rodríguez - dribeas Sep 24 '13 at 16:24
  • @R.MartinhoFernandes: With regards to the answers to my original question, such a "pathological" implementation would indeed be Standard-compliant. And indeed, `operator*` would put a real mess into this well-ordered `optional`. That's a shame, by the way. – Laurent LA RIZZA Sep 24 '13 at 16:25
  • @LaurentLARIZZA In C++11 see §3.9/4 and footnote 42 which says *"The intent is that the memory model of C ++ is compatible with that of ISO/IEC 9899 Programming Language C"*. In C99 see §6.2.6.2. – Simple Sep 24 '13 at 17:03
  • @LaurentLARIZZA: You cannot. Each optional adds informations to (`bool` is a bit, `optional` is trit, `optional>` are 2 bits etc.). On most platform you can have at most `2^CHAR_BIT - 1` nestings to fit in a single byte (for most modern platforms byte == octet == 8). – Maciej Piechotka Sep 24 '13 at 19:12
  • @MaciejPiechotka: That's obvious. (Although I would say 2^CHAR_BIT - 2). The question was: taking into account this limit, how many template partial specializations do you have to write? – Laurent LA RIZZA Sep 25 '13 at 06:50
  • @Simple: I've seen this. This is a statement of intent, not a requirement. I interpret it as "The requirements of the C++ memory model are such that it is compatible with the C99 memory model." But I don't think that it is a licence to import wording from the C99 standard memory model. The C++ memory model is NOT the C99 memory model. – Laurent LA RIZZA Sep 25 '13 at 07:04
25

Storage: how much space does it take, ignoring alignment?

Implementation defined, but in practice one byte. It can't usually be smaller, since that's the smallest possible object size. Exceptions are:

  • bitfield class members can be a single bit;
  • std::vector<bool> packs values so that each takes a single bit; but doesn't really hold objects of type bool. Other types (like std::bitset) do similar things, but don't pretend to be storing bool.

Is there any requirement for the value that will be stored to represent true and false?

No; just the requirement that, when converted to a numeric type, true becomes 1 and false becomes 0. In practice that means that an implementation is likely to use those values; although, on some platforms, other representations might work better.

Values taken: Let b be an object of type bool, does the assertion (b == true) || (b == false) hold?

The assertion will hold if b has been initialised or assigned with a valid value. If it's uninitialised, then it may not hold; but you have undefined behaviour anyway, if you use an uninitialised value. In fact, the standard contains a specific footnote (referenced by C++11 3.9.1/6) warning about this:

47) 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.

UPDATE: the question keeps on growing:

Is (false < true) well-formed, and does it hold?

Yes, and yes. The operands are promoted to int, giving 0 < 1, which is true.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
8

With respect to the size of bool if we look at section 5.3.3 Sizeof from the draft C++ standard it says(emphasis mine):

[...]sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1. The result of sizeof applied to any other fundamental type (3.9.1) is implementation-defined. [ Note: in particular, sizeof(bool), sizeof(char16_t), sizeof(char32_t), and sizeof(wchar_t) are implementation-defined.74 —end note ] [...]

and with respect to the values of bool if we look at section 3.9.1 Fundamental types paragraph 6 says:

Values of type bool are either true or false.47

You also asked:

Values taken: Let b be an object of type bool, does the assertion (b == true) || (b == false) hold? Is (false < true) well-formed, and does it hold?

section 4.5 Integral promotions says in paragraph 6:

A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.

Since operands to < are promoted to int then (false < true) holds assuming that b is properly initialized(you are not invoking undefined behavior) then (b == true) || (b == false) also holds.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
5

There are two possible values, true and false.

Anything else you may observe is the result of undefined behavior.

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
0

Under normal use cases, all non-zero values of data cast as a bool is interpreted as true, and all zero values of data cast as a bool are false. A bool must be at least 1 byte, as all types in C++ must observe this quality.

But I have been enlightened here, and everyone above me deserves an upvote. In an undefined behavior scenario (such as uninitialized or malformed data) bool's can be both true and false at the same time. Such strange behavior, but then again what's undefined is always strange. Thanks everyone for the info.

In the comments: this link to a relevant post.

Community
  • 1
  • 1
Will Custode
  • 4,576
  • 3
  • 26
  • 51
  • That doesn't really answer the question of what values `bool` can have. Any value *converted* to a `bool` is either `false` or `true` -- but what about values derived in other ways? – Keith Thompson Sep 24 '13 at 19:46
  • Explain the difference? At the point of evaluation any value, regardless of its origins, can be interpreted as a bool. And this interpretation is what binds that data to the evaluation rules of a bool, as I explained above. – Will Custode Sep 24 '13 at 19:47
  • 3
    See [R. Martinho Fernandes's answer](http://stackoverflow.com/a/18985007/827263). In the presence of undefined behavior, a `bool` value may be neither `true` nor `false`. – Keith Thompson Sep 24 '13 at 19:50
  • 1
    See [this](http://stackoverflow.com/questions/4518951/engineered-bool-compares-equal-to-both-true-and-false-why). It is possible to create a bool value which compares true to both true and false – BЈовић Sep 25 '13 at 06:22