How bool is stored in memory

Pages: 1234
zapshe wrote:
When bool = 1, it's == to true. You can use std::bitset<8>(true).to_string() and you'd get 00000001. "true" is equal to 1.

What do you mean by "bool = 1" ?
You mean something like bool b = 1; ?
That'll set b to true.

Or you mean the underlying data? I still believe that is up to the "implementation".

zapshe wrote:
Why would true be stored as 10001000..

No particular reason other than it seems to be allowed by the standard, and for the sake of the example.

zapshe wrote:
.. and why would my example output 00000001 if such is the case?

Because the bool value true is converted to the integer value 1 when you pass it to the bitset constructor.

zapshe wrote:
As far as I know, true evaluates to 1.

In C, if you include <stdbool.h> you can use the true macro which expands to 1 (an int).

But in C++ true is a real keyword that gives you a value of type bool. The type is not the same, and the underlying bits are not necessarily the same (although in practice that is usually the case).

bool is implicitly convertible to int, where true will get converted to 1, but that would happen regardless of what bit pattern is used to store the value true.

mbozzi wrote:
I think that program has undefined behaviour, although I'm not entirely sure.

Yeah, I think you're right.

Earlier I was confused by P2624 and the fact that -fsanitize=bool didn't seem to work on GCC but it really seems like it should be treated as UB. It makes the most sense.
Last edited on
You mean something like bool b = 1; ?
Yes

Because the bool value true is converted to the integer value 1 when you pass it to the bitset constructor.

Yes, the boolean value "true" which is 1. But a bool VARIABLE is NOT. I've already proven this:

1
2
3
4
5
int main()
{
	bool a = std::bit_cast<bool>(static_cast<std::uint8_t>(5));
	std::cout << std::bitset<8>(a).to_string() << '\n';
}

00000101


Hence if bool > 1 becomes "true" and then converted to 1, this would not be the output.
Last edited on
That example is probably UB. See mbozzi's post: https://cplusplus.com/forum/beginner/284739/2/#msg1234023

If the bit pattern 00000101 was used for the value true then your example would have to print 00000001. The standard is very clear about this.
Last edited on
I always miss the weirdest threads...

Particularly enlightening reading:
https://stackoverflow.com/questions/33380742/is-it-safe-to-memset-bool-to-0?noredirect=1&lq=1

The reason the standard will not specify how a bool is actually represented is because it might not be what you think, and the standard wants conformant programs to behave the same regardless of what the underlying data representation is. It is the same reason that nullptr is not necessarily an actual zero in memory — weird old dinosaurs exist where it isn’t.

(It would be really obnoxious to have to port a program for a system where 1 is false and 0 is true, and have to comprehensively audit that program for every single boolean expression.)

All said, though, there is no modern hardware (at least, AFAIK) where the underlying value is not internally represented as 0 ≡ false and non-zero ⟶ true, convenient in C and C++ because integer type promotion (and operators) return 0 and 1 for false and true respectively. This is also true of all modern software that I am aware of, which is exponentially less and less every decade.

(Much of this is the case simply because that is how C has done it from the beginning.)

How that underlying value is stored is a separate issue. Both std::bitset and std::vector<bool> store an array of bits, where each bit is a separate boolean value — they use some bitmasking to transform the indexed bit to and from a bool. Some databases use all-bits set as true. Etc etc.

C and/or C++ expressly forbid ordering on bool values. Code that looks like 0 < 1 is valid only because of integer type promotion. I can’t really think of a good way or reason to break that, but I also have never needed to use it.
Last edited on
Duthomhas wrote:
It is the same reason that nullptr is not necessarily an actual zero in memory — weird old dinosaurs exist where it isn’t.

Null for pointers to data members is sometimes implemented as -1: https://godbolt.org/z/bETdTzcdq

This allows pointers to data members to be implemented simply as offsets from the start of the struct. A pointer to the first data member would have offset 0 and therefore null has to use a different value.

https://en.cppreference.com/w/cpp/language/pointer#Pointers_to_data_members


Note that the rules for zero-initialization that always happen for static (e.g. global) variables are specified to make this a non-issue. Pointers are always zero-initialized to null, bools are always zero-initialized to false, and so on, regardless of the underlying bit pattern of those values.
Last edited on
May I continue the conversation a little more further? Thanks.
I don't understand how it could be possible, but the two last requests give as result True. It's a litle bit deconcerting. It seems to me that everything is True except 0. Maybe I did something wrong ++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>

class displayBool {

private:
    void display_bytes(const void* object, size_t size)
    {
        const unsigned char* const bytes = static_cast<const unsigned char*>(object);
        size_t i;

        for (i = 0; i < size; i++)
        {
            int binary[8];

            for (int n = 0; n < 8; n++)
                binary[7 - n] = (bytes[size - 1 - i] >> n) & 1;

            for (int n = 0; n < 8; n++)
                printf("%d", binary[n]);
        }
    }

public:
    displayBool(bool b)
    {
        std::cout << "Value is " << b << std::endl;
        // std::cout << "Address is " << &b << std::endl;
        // std::cout << "Size is " << sizeof(b) << " bytes" << std::endl;

        std::cout << std::boolalpha;
        std::cout << "Boolean is setting to " << b << std::endl;
        std::cout << std::noboolalpha;

        std::cout << "Memory Blocks : ";
        display_bytes(&b, sizeof(b));

        std::cout << std::endl << std::endl;
    }
};

int main() {

    const int size = 6;

    bool aBool[size] { 
        static_cast<bool>(0), 
        static_cast<bool>(1), 
        false, 
        true, 
        static_cast<bool>(-7),
        static_cast<bool>(7) };

    for (size_t i = 0; i < size; i++) 
    {
        displayBool* b = new displayBool(aBool[i]);
        delete b;
    }
   
    return 0;
}
Last edited on
You sent the constructor a value to assign to bool b. That value is then converted to either 0 or 1, true or false.

Others here have been assigning bools values other than 0 and 1 by converting the bool pointer through casting.


Either way, anything that's not 0 is considered true. However, if you use the keyword "true" that has a value of 1. But 1 is not the only value considered to be true.
Thanks for your comment. You said :
Either way, anything that's not 0 is considered true.

Is your explanation about my code (so maybe I made a mistake) or this is THE rule for modern computing?
Last edited on
Oh. I did not see the previous code given by GLBorges. It's clear :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <bitset>
#include <limits>

int main()
{
    if constexpr( sizeof(bool) == sizeof(unsigned char) )
    {
        using bits = std::bitset< std::numeric_limits<unsigned char>::digits > ;

        bool b = true ;
        unsigned char& c = reinterpret_cast<unsigned char&>(b) ;

        for( unsigned int v : { 0, 1, 99, 128, 255 } )
        {
            c = v ;
            std::cout << v << ' ' << std::boolalpha << b << ' ' << int(b) << ' ' << int(c) << ' ' << bits(c) << '\n' ;
        }
    }
}


https://www.cs.uic.edu/~jbell/CourseNotes/CPlus/Decisions.html
For interpretation, Zero is interpreted as false and anything non-zero is interpreted as true.
Last edited on
This thread is probably confusing some people because there are really three discussions going on. I would therefore like to write a small summary to try and clarify...

How are true and false stored in memory?
False is usually stored in binary as 00000000 and true is usually stored as 00000001 but this is up to the compiler.

What happens when you convert between bool and integers?
When converting a bool to an integer false will become 0 and true will become 1.
When converting an integer to a bool zero will become false while all other values will become true. This is essentially what happens if you try to use an integer where a boolean expression is expected (e.g. as a condition to an if statement or a while loop).

What happens if you force a different bit pattern that does not represent true or false to be stored in a bool (using pointer casts or std::bit_cast)?
Different compilers handle it differently. It's probably UB. Don't do it.
Last edited on
It is UB.
UB? May be. According to p2624, there is a contradiction in the standard.

The C++20 standard (6.8.210) states: Type bool is a distinct type that has the same object representation, value representation, and alignment requirements as an implementation-defined unsigned integer type. The values of type bool are true and false. However, if the bool type can have just two values, it cannot have the same value representation as the underlying unsigned integer type, which can take at least 256 distinct values. In view of this contradiction, no implementation can conform exactly to the standard; they approximate the standard in different ways, with observably different consequences.
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2624r0.html


Proposal:
6.8.2 Fundamental types [basic.fundamental]

10 Type bool is a distinct type that has the same object representation, value representation, and alignment requirements as an implementation-defined unsigned integer type. The values of type bool are true and false. Each possible value of the unsigned integer type used for the object representation shall be interpreted either as the value true or as the value false for the type bool. It is implementation-dependent which values of the unsigned integer type are interpreted as true and which are interpreted as false, except that the value zero shall necessarily be interpreted as false and the value one shall necessarily be interpreted as true.


The two alternatives:
(i) A minimal resolution of the issue would be to have the standard state that undefined behavior results whenever the unsigned integer object holding a bool has a value other than 0 or 1. This option would obviate the need to amend any existing implementation but, to be fully portable, code would need to check the value of a bool of unknown provenance before using it, such as by promoting it to int and converting it back to bool.

(ii) A maximal resolution would be to specify a common representation of bools for all implementations. This would maximize portability but would involve greater changes to some implementations’ semantics for bools.
Ah I see. So when a girl asks if she looks nice, any compliment other than true/false will lead to undefined behavior.
> So when a girl asks if she looks nice, any compliment other than true/false will lead to undefined behavior.

Whether it is undefined behaviour or unspecified behaviour, if the programmer expects a value other than true or false as a valid answer, why would it be represented as a bool?
Whether it is undefined behaviour or unspecified behaviour, if the programmer expects a value other than true or false as a valid answer, why would it be represented as a bool?

Lmao, I wasn't making any point, just a dumb joke.

A char would work just fine for the same purpose.
Well first thank you everyone for you generosity, I am honored to met such amazing minds.

Second, I am following each comment with enthusiasm, but i cannot reply simply because my c++ knowledge is pre-cx98 and it sucks, also I was expecting the answer to be simple, but you took this topic to higher level I still not reached yet.

Third, I have so many questions related to this topic, so allowed me to extend it even more. I might take some time before reply, but that's only because I am currently doing some catch up.

@Peter87 just provide one of the best link I ever saw.
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2624r0.html
What is the story of this website?

It seems to me that it is gathering of programmers finding the bugs about the standard, am I right?
my c++ knowledge is pre-cx98

"Learn C++". Spend some time mucking around the free site, to learn newer ideas and ways of mashing C++ code.

https://www.learncpp.com/

The site is still being updated frequently.
Thanks @George P, I am currently reading the 4th edition of c++ programming language, and to be honest that's a pain, I think the books is for pros, anyway, I will overcome it.

and thanks for the link)
ninja01 wrote:
I am following each comment with enthusiasm, but i cannot reply simply because my c++ knowledge is pre-cx98 and it sucks, also I was expecting the answer to be simple, but you took this topic to higher level I still not reached yet.

People here are eager to discuss things. Even simple things have complicated details.

I don't think it is as complicated as this thread makes it seem. That's why I wrote the summary: https://cplusplus.com/forum/beginner/284739/3/#msg1234041
(the important thing to know is the answer to the second question)

ninja01 wrote:
@Peter87 just provide one of the best link I ever saw.
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2624r0.html
What is the story of this website?

It seems to me that it is gathering of programmers finding the bugs about the standard, am I right?

If you want to change something in the C++ standard you need to write a proposal. P2624 is such a proposal.

You can find many more proposals here: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/
Click on a year and you'll see all the proposal papers for that year.
Note that proposals are often updated. That's why there are multiple papers for the same proposal with different "revision" number.

P2624R0 <-- Paper 2624 revision 0 (i.e. the first version of this proposal)

Older papers might use different naming schemes.

You can read more about the status of various proposals by looking them up here: https://github.com/cplusplus/papers/issues/
(Note that this is not a place for submitting new proposals or commenting on the content of the proposals)

You find more information about the standardisation process at https://isocpp.org/std
Last edited on
I am currently reading the 4th edition of c++ programming language


Assuming that is "The C++ Programming Language" by Bjarne Stroustrup
https://www.amazon.co.uk/C-Programming-Language-Bjarne-Stroustrup/dp/0321563840/ref=sr_1_3

Then that is the last 'reference' C++ book published by Stroustrup (who created the C++ language). It is NOT a tutorial book for learning the C++ language (unlike his other books) - and only covers C++11 and hasn't been updated since. It is a reference book which explains the whole of the C++ language in great technical detail. Unless you are already quite familiar with C++ then that book is more likely to confuse then to educate. Not recommended. For that type of C++ detail you're better off using the cppreference site - https://en.cppreference.com/w/cpp


For some better books consider:

C++20 - Beginning C++20 - From Novice to Professional by Ivor Horton
https://www.amazon.co.uk/Beginning-C-20-Novice-Professional/dp/1484258835/ref=sr_1_3

Professional C++ (5th Edition) by Marc Gregorie
https://www.amazon.co.uk/Professional-C-Marc-Gregoire/dp/1119695406/ref=sr_1_4

Also there are specific C++17/C++20 ebooks on leanpub
https://leanpub.com/bookstore?search=c%2B%2B&type=all&page=2

I suggest books by Grimm, Josuttis, Filipek
Last edited on
Pages: 1234