using Boolean to represent integers - c++

In c++, bool is used to represent Boolean. that is it holds true or false. But in some case we can use bool to represent integers also.
what is the meaning of bool a=5; in c++?

"what is the meaning of bool a=5; in c++?"
It's actually equivalent to writing
bool a = (5 != 0);
"But in some case we can use bool to represent integers also."
Not really. The bool value only represents whether the integer used to initialize it was zero (-> false) or not (-> true).
The other way round (as mentioned in #Daniel Frey's comment) false will be converted back to an integer 0, and true will become 1.
So the original integer value's (or any other expression results like pointers, besides nullptr, or double values not exactly representing 0.0) will be lost.
Conclusion
As mentioned in LRiO's answer, it's not possible to store information other than false or true in a bool variable.
There are guaranteed rules of conversion though (citation from cppreference.com):
The safe bool problem
Until the introduction of explicit conversion functions in C++11, designing a class that should be usable in boolean contexts (e.g. if(obj) { ... }) presented a problem: given a user-defined conversion function, such as T::operator bool() const;, the implicit conversion sequence allowed one additional standard conversion sequence after that function call, which means the resultant bool could be converted to int, allowing such code as obj << 1; or int i = obj;.
One early solution for this can be seen in std::basic_ios, which defines operator! and operator void* (until C++11), so that the code such as if(std::cin) {...} compiles because void* is convertible to bool, but int n = std::cout; does not compile because void* is not convertible to int. This still allows nonsense code such as delete std::cout; to compile, and many pre-C++11 third party libraries were designed with a more elaborate solution, known as the Safe Bool idiom.

No, we can't.
It's just that there's an implicit conversion from integer to boolean.
Zero becomes false; anything else becomes true.

In fact this declaration
bool a=5;
is equivalent to
bool a=true;
except that in the first declaration 5 as it is not equal to zero is implicitly converted to true.
From the C++ Standard (4.12 Boolean conversions )
1 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer
to member type can be converted to a prvalue of type bool. A zero
value, null pointer value, or null member pointer value is converted
to false; any other value is converted to true. For
direct-initialization (8.5), a prvalue of type std::nullptr_t can be
converted to a prvalue of type bool; the resulting value is false.
One more funny example
bool a = new int;
Of course it does not mean that we may use bool to represent pointers. Simply if the allocation is successfull then the returned poimter is not equal to zero and implicitly converted to true according to the quote I showed.
Take into account that till now some compilers have a bug and compile this code successfully
bool a = nullptr;
Though according to the same quote a valid declaration will look like
bool a( nullptr );

And, basically, I would opine that bool b=5 is "just plain wrong."
Both C and C++ have a comparatively weak system of typing. Nevertheless, I'm of the opinion that this should have produced a compile error ... and, if not, certainly a rejected code review, because it is (IMHO) more likely to be an unintentional mistake, than to be intention.
You should examine the code to determine whether b is or is not "really" being treated as a bool value. Barring some "magic bit-twiddling purpose" (which C/C++ programs sometimes are called-upon to do ...), this is probably a typo or a bug.
Vlad's response (below) shows what the standard says will happen if you do this, but I suggest that, "since it does not make human-sense to do this, it's probably an error and should be treated accordingly by the team.
A "(typecast)?" Maybe. A data-type mismatch such as this? Nyet.

Related

How is a bool represented in memory?

As already discussed in the docs, a bool data type occupies at least a byte of memory. A similar question was asked on SO before (How a bool type variable is stored in memory? (C++)), but this discussion and the documentation only seem to discuss the amount of space occupied by a boolean data type, not what actually happens in memory when I do this:
bool b = true;
So what does actually happen in memory? What happens to the 7 bits that are not used in storing this information? Does the standard prescribe behavior for this?
Are they undefined? Or did someone at C++ headquarters just do this:
enum bool : char
{
false = 0,
true = 1
};
Standard states that bool values behave as integral types, yet it doesn't specify their concrete representation in memory:
"Values of type bool are either true or false. As described below, bool values behave as integral types. Values of type bool participate in integral promotions" ~ C++03 3.9.1 §6
"A synonym for integral type is integer type. The representations of integral types shall define values by use of a pure binary numeration system" ~ C++03 3.9.1 §7
Yet it defines the integral promotion from bool to int:
"An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true becoming one. These conversions are called integral promotions." ~ C++03 4.5 §4-5
as well as conversion from other types to bool:
"A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true." ~ C++03 4.12 §1
The standard doesn't mandate anything for the binary representation of bools; it just says that, when converting to other integral types, a true bool will become 1 and a false bool will become 0.
This of course suggests an implementation similar in spirit to the one you said, where such conversions would become essentially no-ops or plain integer widening (but remember that bool is mandated to be a primitive type, not an enumeration type).
You can test things like this by copying the memory, ignoring which type it is. This program reads the raw memory value of test_bool and puts it into test_int so that you may print it.
int test_int = 0;
bool test_bool;
test_bool = true;
memcpy (&test_int, &test_bool, sizeof(bool));
printf ("True value is: %d\n", test_int);
test_bool = false;
memcpy (&test_int, &test_bool, sizeof(bool));
printf ("False value is: %d\n", test_int);
For me, this program gives:
True value is: 1
False value is: 0
I didn't program in C++ since a couple of months but AFAIR the rule is the following:
0 - false;
any value different than 0 - true; (by default it's 1 but AFAIR if you convert it from other integer value, ex. 2 will be also treated as true).
Thus you can say that C++ in some way waste memory (others too) as it could use one bit only but it's simpler to make compiler then.
In C++ you can also define bit fields (bit fields in wikipedia) but it's not used often.

Casting 0-1 int r-value to bool

I have an expression which returns 0 or 1 integer as a temporary value. The value is probably already in a register and I would like to return it as a bool from an inlined function.
Is there an ordinary way to do this? I believe (bool) and static_cast<bool> inject additional test and set instructions. And this is too much for me, while the case is about a performance critical part of memory manager.
Just return it. Any value, different from 0 is true and 0 is false in c++.
Just return the int from your inline function (which returns bool).
Assuming your integer expression is foo, then use !!foo to get the bool value.
What are you doing with the return value? If you are using it
immediately in condition, the compiler will probably generate
exactly the same code, regardless of whether the type is bool
or not. There will be a simple comparison with 0. If you are
assigning it to a bool variable, the compiler will generally
generate an extra instruction, to ensure that the binary value
is either 0 or 1 (and not some other value). But what is
the expression, so that you can be sure that it is either 0 or
1? If it is something like x & 1, a good compiler will
recognize this, and will optimize out the extra instruction.
EDIT:
I might add that I am assuming inlining and optimization.
If performance is an issue, those are the first two steps
you should take.
When I come across such performance warnings in cppcheck, I usually use the most elegant approach for this (at least in my opinion ;) ):
return yourInt != 0;
This sticks with the assumption that all values different from 0 are considered true.
how about
return rtVal;
just return the integer will return true if it isn't 0
from c++ 2012 standard (ISO/IEC N3337):
4.12 Boolean conversions
A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a
prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false;
any other value is converted to true. A prvalue of type std::nullptr_t can be converted to a prvalue of
type bool; the resulting value is false.
So just return it?!

Magic of casting value to bool

Today I realized that casting a value to a bool is a kind of magic:
int value = 0x100;
unsigned char uc = static_cast<unsigned char>(value);
bool b = static_cast<bool>(value);
Both sizeof(uc) and sizeof(b) return 1. I know that uc will contain 0x00, because only the LSB is copied. But b will be true, so my assumption is that, when casting to bool, the value gets evaluated instead of copied.
Is this assumption correct? And is this a standard C++ behavior?
There's nothing magical about it. The conversion from int to unsigned char is defined as value % 256 (for 8-bit chars), so that is what you get. It can be implemented as copying the LSB, but you should still think about it in the semantic sense, not the implementation.
On the same vein, conversion of int to bool is defined as value != 0, so again, that is what you get.
Integral (and boolean) conversions are covered by the C++11 standard in [conv.integral] and [conv.bool]. For the C-style cast, see [expr.cast] and [expr.static.cast].
It is a part of the standard:
4.12 Boolean conversions [conv.bool]
1 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer
to member type can be converted to a prvalue of type bool. A zero
value, null pointer value, or null member pointer value is converted
to false; any other value is converted to true. A prvalue of type
std::nullptr_t can be converted to a prvalue of type bool; the
resulting value is false.
Yes, when casting to bool, the value gets evaluated, not copying.
In fact, in your example, as long as value is not 0, b will be true.
Update: Quoting from C++ Primer 5th Edition Chapter 2.1.2:
When we assign one of the nonbool arithmetic types to a bool object, the
result is false if the value is 0 and true otherwise.
According to the rules for C-style casts, (bool)value is effectively a static_cast. The first rule for static_cast then kicks in, which computes the value of a temporary "declared and initialized ... as by new_type Temp(expression);", i.e. bool Temp(value);. That's well-defined: Temp is true iff value != 0. So yes, value is "evaluated" in a sense.
Casting to bool is a feature inherited from plain old C. Originally, C didn't have a bool type, and it was useful to use other types in if statements, like so:
int myBool = 1;
if(myBool) {
// C didn't have bools, so we had to use ints!
}
void* p = malloc(sizeof(int));
if(!p) {
// malloc failed to allocate memory!
}
When you're converting to bool, it acts just like you're putting the statement in an if.
Of course, C++ is backwards compatible with C, so it adopted the feature. C++ also added the ability to overload the conversion to bool on your classes. iostream does this to indicate when the stream is in an invalid state:
if(!cout) {
// Something went horribly wrong with the standard output stream!
}
ISO/IEC C++ Standard:
4.12 Boolean conversions [conv.bool] 1 A prvalue of arithmetic... type can be converted to a prvalue of type bool. A zero value... is converted to false; any other value is converted to true.
So, since a prvalue is a value, you might say that the value gets evaluated, albeit that's kind of pleonastic.

Conversion function for error checking considered good?

I'd like to have a simple way of checking for an object to be valid. I thought of a simple conversion function, something like this:
operator bool() const { return is_valid; }
Checking for it to be valid would be very simple now
// is my object invalid?
if (!my_object) std::cerr << "my_object isn't valid" << std::endl;
Is this considered a good practise?
In C++03, you need to use the safe bool idiom to avoid evil things:
int x = my_object; // this works
In C++11 you can use an explicit conversion:
explicit operator bool() const
{
// verify if valid
return is_valid;
}
This way you need to be explicit about the conversion to bool, so you can no longer do crazy things by accident (in C++ you can always do crazy things on purpose):
int x = my_object; // does not compile because there's no explicit conversion
bool y = bool(my_object); // an explicit conversion does the trick
This still works as normal in places like if and while that require a boolean expression, because the condition of those statements is contextually converted to bool:
// this uses the explicit conversion "implicitly"
if (my_object)
{
...
}
This is documented in §4[conv]:
An expression e can be implicitly
converted to a type T if and only if
the declaration T t=e; is well-formed,
for some invented temporary variable t
(§8.5). Certain language constructs
require that an expression be
converted to a Boolean value. An
expression e appearing in such a
context is said to be contextually converted to bool and is well-formed
if and only if the declaration bool t(e); is well-formed, for some
invented temporary variable t (§8.5). The effect of either
implicit conversion is the same as performing the
declaration and initialization and then using the temporary
variable as the result of the conversion.
(What makes the difference is the use of bool t(e); instead of bool t = e;.)
The places were this contextual conversion to bool happens are:
the conditions of if, while, and for statements;
the operators of logical negation !, logical conjunction &&, and logical disjunction ||;
the conditional operator ?:;
the condition of static_assert;
the optional constant expression of the noexcept exception specifier;
No, a simple bool conversion operator is not, as you can now make evil comparisions between unrelated types. Generally, yes, a conversion function is a-okay. Just use the right one (safe-bool idiom). I can't explain it any better than the given links.
The original question was
Is this considered a good practise?
The issue with the safe bool conversion was very relevant in practice, but fortunately has now been addressed by the standards.
But the judgement if this approach is appropriate, is a question of design.
By introducing such a "validity check", effectively you are stating that your objects can be in an invalid state. That is, speaking in the terms of computer science, you added a new separate value to the value domain represented by your objects. A so called bottom value
The most prominent example for a value domain with that propery is the pointer. A pointer can refer to various memory locations, but it also can be NULL (invalid).
Thus we need do ask ourselves: does such a bottom value really reflect the nature of the things we want to model with our classes -- and -- do we really need to cover this aspect of the nature within our model?
Experience shows that bottom values tend to be error prone, easy to forget and generally more of a liability than an asset. If you're able to arrange your code in a way that your objects can not be invalid, your code gets simpler, easier to read, to understand and to maintain..

Why this weird compatibility of bool and pointers in C++?

Not only is this valid and doesn't give any warnings even with -Wall:
void* p = false; // actually 'true' doesn't work here
bool b = "Hello, Boolean!";
but also this compatibility rule permits selecting an overloaded function/operator for a wrong type. Let's say you overloaded your operator << for all fundamental types and you forgot to overload the void pointer, then the compiler may select the version that takes bool, or the other way around.
So what is it that makes this compatibility rule more important than the weird (and highly undesirable) side effects with overloaded functions?
(Edit: removed all references to C, they were wrong: the conversion rules are basically the same in C.)
What do you mean by "C can handle this correctly"? C doesn't permit function overloading, so you are guaranteed to have the bool <-> pointer conversion you're complaining about.
Are you asking why this conversion exists?
The first is not actually a conversion bool -> pointer, but is recognizing that the literal false means 0, which is a valid pointer value. That's why it doesn't work with true, and it doesn't work with a bool variable.
The second is because it's nice to be able to write:
if (p)
instead of
if (p != 0)
to check if a pointer holds a null pointer value.
EDIT: Rules from the standard influencing T* p = false;:
A null pointer constant is an integral constant expression prvalue of integer type that evaluates to zero
and
Types bool, char, char16_t, char32_t, wchar_t, and the signed and unsigned integer types are collectively called integral types. A synonym for integral type is integer type.
and
The Boolean literals are the keywords false and true. Such literals are prvalues and have type bool.