1

Updates: The reason I was getting true is because anything that is other than 0 would be considered true which obviously makes sense to how unlikely it would have been for me to get false when uninitialized.

I have read a post similar to my question on StackOverflow, it talked about that it is good practise to initialize all member variables, which I agree with. Post: Boolean variables aren't always false by default?

This post is a bit old (9 years ago) so I just think maybe somethings might have been changed in the new C++ versions, I am currently using C++17. I also have one slight different question from the ones talked about in the post.

I am aware that if a variable is uninitialized it may contain some "garbage data" or as one of the answers in the post said (which I think that is what they meant but I'm not 100% sure), "if not explicitly initialized -- will contain an arbitrary value.".

I have tried testing that, and the results showed that when I didn't initialize my variables, they contained random numbers (for int, double). I also tested std::string but they are set to "" by default from what I saw.

Anyways, now when I tried for the built in type bool I would always get true (after class is constructed, but again that boolean value never initialized, I would go into debug and see that the value would be true), what I am confused is that no matter how many times I tried to test if that was just a random value out of true and false, and if sometimes it would be false, it was always set to true. If uninitialized shouldn't the value be "random" kind of? Why did it always set to true (again when a member variable of my class which wasn't initialized on construction).

Solutions I tried: Obviously one is just to initialize on construction, but I thought of another one...

What if on construction I wanted it to be true and not false but when it hasn't been constructed to be set to false then that way when I have a vector of pointers to my object I can check that I am not reading uninitialized objects when following the pointer by checking whether that boolean is set to true (if initialized) or false otherwise. I wouldn't be able to use method 1 which was to initialize on construction to false, also because if we are reversing the behaviour I can't rely on what that uninitialized boolean member variable would be as I mentioned in the above paragraphs I am unsure what behaviour that has due to the results I had been getting. I did the following and it worked...

class Testing{
private:
    bool condition{false} // Initalize it here which kind of makes me confused but it works

public:
    Testing() : condition{true} {} // Constructor setting the condition value to true

};

Could someone explain if it is wrong to do this, personally I have never seen someone do this but I tried it and no errors were given.

Krapnix
  • 257
  • 2
  • 8
  • 1
    Implementation specific - false is usually held as 0 and true as any other value. So you would expect more true results. However the program has Undefined Behaviour (reading an uninitialized value) so any analysis and reasoning about its behaviour is meaningless. – Richard Critten Dec 18 '20 at 12:39
  • You're seeing more true because any non zero value are casted to true – Moia Dec 18 '20 at 12:40
  • Uninitialized variables are uninitialized, and have no initial value. It's possible that some architectures would mark the memory as *uninitialized*, and trying to **read** from it would cause the program to fault and terminate — that's one possibility (of many) for *undefined behavior*. Your code that initializes the `bool` will have a known initial value, and that typically is a Good Thing™. – Eljay Dec 18 '20 at 12:42
  • 1
    The uninitialized value isn't random. It's arbitrary. And I'm pedantic. Run the program in your debugger and see if the numeric value of the bool is always constant, or if it's a different non-zero number every time. – JohnFilleau Dec 18 '20 at 12:42
  • *I also tested std::string but they are set to "" by default from what I saw.* -- That is because the default constructor for `std::string` sets the string to empty. It is impossible to have an uninitialized `std::string`. – PaulMcKenzie Dec 18 '20 at 12:46
  • @JohnFilleau I tried several times to check on the debugger but it showed this (Microsoft Visual Studio 2019) for my boolean variable called "init": `init | true(204) | bool` the number 204 next to the true would never change but I'm not sure what that means. – Krapnix Dec 18 '20 at 12:54
  • @Krapnix: It means your environment is so stable and reproducible, that you get the same value every time. Change anything and that value will most likely also change. – U. W. Dec 18 '20 at 13:12

1 Answers1

2

While bool conceptually contains only one bit of information, the requirements of the C++ standard mean that a bool object must take up at least eight bits. There's three main ways that a compiler might represent bool at a bitwise level:

  1. All bits zeroed for false; all bits one'd for true (0x00 versus 0xFF)
  2. All bits zeroed for false; the lowest bit one'd for true (0x00 versus 0x01)
  3. All bits zeroed for false; at least one bit one'd for true(0x00 versus anything else)

(Note that this choice of representation is not ordinarily visible in the effects of a program. Regardless of how the bits are represented, a bool becomes a 0 or 1 when casted to a wider integer type. It's only relevant to the machine code being generated.)

In practice, modern x86/x64 compilers go with option 2. There are instructions which make this straightforward, it makes casting bool to int trivial, and comparing bools works without additional effort.

A side effect is that if the bits making up a bool end up set to, say, 0x37, weird stuff can happen, because the executable code isn't expecting that. For instance, both branches of an if-statement might be taken. A good debugger should loudly yell at you when it sees a bool with an unexpected bit pattern, but in practice they tend to show the value as true.

The common theme of all those options is that most random bit patterns are not the bit pattern for false. So if the allocator really did set it to a "random" value, it almost certainly would be shown as true in the debugger.

Sneftel
  • 40,271
  • 12
  • 71
  • 104
  • Please remember that array has its special implementation to reduce memory footprint and actually uses only one bit per bool, which creates some interesting problems in some special cases... – U. W. Dec 18 '20 at 15:24
  • @U.W. I think you're thinking of `vector`, which does handle this specially. But the elements of `vector` are never uninitialized. – Sneftel Dec 18 '20 at 15:29