3

I have this class which has a private bool member variable call positive. I want to check to see if both my class and the number I am adding to it are both positive so I wrote the expression

positive == (n > 0) //n is of type int

But for some reason when both are positive this evaluates to false. I then did a cout on positive and it has a value of 204! I though a boolean only holds 1 or 0. That would be why this is evaluating to false but why is that and how do I fix it? I am using Visual Studio 2013.

Just to clarify it should be == because I want to know if the sign is the same. So I want it to be true if both are negative or both are positive. I think I solved the problem which was that positive in one particular test case wasn't being initialized. But still why would a bool variable even if uninitialized contain a value larger and 1?

chasep255
  • 11,745
  • 8
  • 58
  • 115

2 Answers2

4

As per the standard, getting the value of an uninitialized variable is undefined behavior. Since the actual size of a bool can be more than one bit, a bool variable containing rubbish can even hold bad values like 254. Welcome in the C++ hell!

And since (n > 0) evaluates to 1, 254 == 1 is false.

The bug is most likely due to the fact that positive never got a meaningful value since the object that contains it come into existence.

Search for a positive = something into your code and see if it is executed at least once before you use it.


Edited after Konrad comment:

The problem is most likely due to the fact that == is implemented between int-s and not bool-s relying on a bool-to-int promotion assuming the implementation of bool use 0 for false and 1 for true (and since && and || between int-s assume 0 for false and non-zero for true, bool-to-int promotion can be an identity).

This can be seen as a "compiler unfairness", but -since in the space of integer there is one false and bilions of trues- if operator==(bool,bool) was applied, there where more chance the uninitialized bug wold have been not discovered.

Treating bool as int in the arithmetic operations (not logic ones) makes bad-bool values to come out, thus revealing the bug.

Of course, since behind it there is an UB, it's all in an implementation choice. And it is int the freedom of each reading this to think I'm try to sell a bug as a feature.

Emilio Garavaglia
  • 20,229
  • 2
  • 46
  • 63
  • Repeating my comment from another answer: C++ has native `bool`. The results of conditional expressions are `true` and `false`, not `1` and `0`. – Konrad Rudolph Nov 27 '13 at 14:43
  • but `true` must conver to to int to be compared with 254. The problem is that == is most likely implemented between integer and not bool. So bool have to convert to int, and whatever "bad value" comes out. – Emilio Garavaglia Nov 27 '13 at 14:46
  • I believe `==` is implemented between `bool`s (but I’m too lazy to check) – but since the compiler assumes defined behaviour, it can simply take a shortcut and compare the bit values of the operands without checking their validity. That doesn’t preclude the fact that `n>0` evaluates to `true` or `false`. Which bits in memory these correspond to is completely unspecified, they could theoretically be very exotic values. – Konrad Rudolph Nov 27 '13 at 15:01
  • The OP tagged as "Visual C++". For that particular case, MS compiler use 0 for false and 1 for true on a int-sized variable. Where does 254 (0x000000FE) comes out is another issue (most likely depends on what was in memory in the same place `positive` resides: 0xFEFEFEFE is the debug signature for "uninitialized stack ...) – Emilio Garavaglia Nov 27 '13 at 15:18
-1

Oh, you have a == where you should have an =.

The == doesn't assign, it checks for equality

Should be

bool positive = (n > 0) //n is of type int

bool generally holds only 1 or 0 after assignment. The only reason I can imagine you would see 204 in a bool is if the variable was uninitialized (so it had a junk value).

bobobobo
  • 64,917
  • 62
  • 258
  • 363
  • 2
    If I'm reading the question correctly, the quoted code was the _expression_ that chasep255 was trying to evaluate rather than the _statement_ that set `positive`, in which case `==` may be appropriate (or perhaps it should have been `&&`). – Adrian McCarthy Nov 27 '13 at 13:48
  • 4
    “`bool` generally holds only 1 or 0 after assignment” – It doesn’t. It holds `true` or `false`. That’s a different thing. – Konrad Rudolph Nov 27 '13 at 14:04
  • @KonradRudolph `true` is implemented as binary 1, `false` is implemented as binary 0. There is nothing special about `true` and `false`, they are merely 1 and 0 respectively. [See here](http://stackoverflow.com/questions/2725044/can-i-assume-booltrue-int1-for-any-c-compiler). – bobobobo Nov 27 '13 at 14:24
  • 2
    @bobobobo That’s wrong. You’re confusing semantics and low-level implementation. The link you posted is likewise irrelevant: all it tells as that if you *convert* a boolean to an integer, it takes the values 0 or 1. But an implementation is perfectly at liberty to implement `true` and `false` as `234` and `348`, respectively (or, of more practical relevance, as `-1` and `0`). But even if the C++ standard mandated a particular implementation for `bool` (it doesn’t!) that would *still* be irrelevant for the semantics. And the semantics are clear. – Konrad Rudolph Nov 27 '13 at 14:36
  • The fact remains that `bool` is almost always implemented as a binary 0 or 1. So "almost always" that you'd probably consider it a wild goose chase to find a compiler that does otherwise. As you know, the most common implementation of `std::vector` usually exploits this to "save space" by storing each value in a single bit. I'd consider your comment "misleadingly pedantic", where you're trying to say that something has more behind it than it really does, practically speaking. – bobobobo Nov 27 '13 at 15:45
  • 2
    @bobobobo You **still** confuse implementation with semantics. A boolean, *regardless of its implementation*, never has the values `1` or `0`, it *only* takes the values `true` and `false`. My comment isn’t in the least pedantic. The fact that you think so suggests a lack of understanding of abstraction, which is a serious problem in programming. As a primer I suggest reading about [Magritte’s famous painting](https://en.wikipedia.org/wiki/The_Treachery_of_Images) and to follow up on the links in that article (especially the map–territory article). Or, simpler: correct definitions matter. – Konrad Rudolph Nov 27 '13 at 16:59
  • _Seeing past abstractions_ is not a problem -- not understanding the concrete nature of something _behind the abstraction_ is a problem. – bobobobo Nov 27 '13 at 18:45