Can I assume (bool)true == (int)1 for any C++ compiler ?
Yes. The casts are redundant. In your expression:
true == 1
Integral promotion applies and the bool value will be promoted to an int and this promotion must yield 1.
Reference: 4.7 [conv.integral] / 4: If the source type is bool... true is converted to one.
Charles Bailey's answer is correct. The exact wording from the C++ standard is (§4.7/4): "If the source type is bool, the value false is converted to zero and the value true is converted to one."
Edit: I see he's added the reference as well -- I'll delete this shortly, if I don't get distracted and forget...
Edit2: Then again, it is probably worth noting that while the Boolean values themselves always convert to zero or one, a number of functions (especially from the C standard library) return values that are "basically Boolean", but represented as ints that are normally only required to be zero to indicate false or non-zero to indicate true. For example, the is* functions in <ctype.h> only require zero or non-zero, not necessarily zero or one.
If you cast that to bool, zero will convert to false, and non-zero to true (as you'd expect).
According to the standard, you should be safe with that assumption. The C++ bool type has two values - true and false with corresponding values 1 and 0.
The thing to watch about for is mixing bool expressions and variables with BOOL expression and variables. The latter is defined as FALSE = 0 and TRUE != FALSE, which quite often in practice means that any value different from 0 is considered TRUE.
A lot of modern compilers will actually issue a warning for any code that implicitly tries to cast from BOOL to bool if the BOOL value is different than 0 or 1.
I've found different compilers return different results on true. I've also found that one is almost always better off comparing a bool to a bool instead of an int. Those ints tend to change value over time as your program evolves and if you assume true as 1, you can get bitten by an unrelated change elsewhere in your code.
If I write the code:
int a=true;
cout<<a;
The output will be:
1
So yes, you can assume (bool)true==(int)1
Related
I have read the answers to that question: Why is a char and a bool the same size in c++? and made an experiment to determine the size of allocated bytes in memory of a _Bool and a bool(I know that bool is a macro for _Bool in stdbool.h but for the sake of completeness I used it too) object in C, as well a bool object in C++ on my implementation Linux Ubuntu 12.4:
For C:
#include <stdio.h>
#include <stdbool.h> // for "bool" macro.
int main()
{
_Bool bin1 = 1;
bool bin2 = 1; // just for the sake of completeness; bool is a macro for _Bool.
printf("the size of bin1 in bytes is: %lu \n",(sizeof(bin1)));
printf("the size of bin2 in bytes is: %lu \n",(sizeof(bin2)));
return 0;
}
Output:
the size of bin1 in bytes is: 1
the size of bin2 in bytes is: 1
For C++:
#include <iostream>
int main()
{
bool bin = 1;
std::cout << "the size of bin in bytes is: " << sizeof(bin);
return 0;
}
Output:
the size of bin in bytes is: 1
So, objects of a boolean type, regardless of specifically C or C++, occupy 1 byte (8 bits) in memory, not just 1 bit.
My question is:
Why do objects of the types bool and _Bool in C and bool in C++ can store only the values of 0 or 1 if they occupy 1 byte in memory which could hold 256 values?
Of course, Their purpose is to represent only the values of 0 and 1 or true and false, but which unit or macro decides that it only can store 0 or 1?
Additional, but not my main question:
And what would happen if the value of a boolean type is *accidentally modified in memory to a greater value since it can be stored in memory this way?
*With accidentally I mean either: Modified by "Undetectable means" - What are “undetectable means” and how can they change objects of a C/C++ program? or an inappropriate assignment of f.e. bool a; a = 25;.
The C language limits what can be stored in a _Bool, even if it has the capacity to hold other values besides 0 and 1.
Section 6.3.1.2 of the C standard says the following regarding conversions to _Bool:
When any scalar value is converted to _Bool, the result is 0 if the value compares equal
to 0; otherwise, the result is 1.
The C++17 standard has similar language in section 7.14:
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 (11.6), a prvalue of type std::nullptr_t can
be converted to a prvalue of type bool; the resulting value is false.
So even if you attempt to assign some other value to a _Bool the language will convert the value to either 0 or 1 for C and to true or false for C++. If you attempt to bypass this by writing to a _Bool via a pointer to a different type, you invoke undefined behavior.
Answer for C++:
So, objects of a boolean type, regardless of specifically C or C++, occupy 1 byte (8 bits) in memory, not just 1 bit.
That's simply because the fundamental storage unit in the C++ memory model is the byte.
Why do objects of the type [...] bool in C++ can store only the values of 0 or 1 if they occupy 1 byte in memory which could hold 256 values?
But which unit or macro decides that it only can store 0 or 1?
The assumption here is wrong. In C++, a bool does not hold 0 or 1, it holds false or true: http://eel.is/c++draft/basic.fundamental#10.
How those two values are represented in memory is up to the implementation. An implementation could use 0 and 1, or 0 and 255, or 0 and <any nonzero value>, or anything it wants really. You are not guaranteed to find 0 or 1 when inspecting the memory of a bool, because...
If you "assign" e.g. an integer or a pointer to a bool, it is implicitly converted to either true or false according to the usual rules: http://eel.is/c++draft/conv.bool#1
If you "read" an integer from a bool, it is implicitly converted to 0 if it held the value false or 1 if it held the value true: http://eel.is/c++draft/conv.prom#6
It is the job of the compiler to ensure that the above two things hold true, regardless of how the bool values are represented in memory. Remember, C++ is specified on the abstract machine, and your program only has to behave as if executed on the abstract machine.
And what would happen if the value of a boolean type is accidentally modified in memory to a greater value?
Undefined behavior. See one of these:
Why does bool and not bool both return true in this case?
Engineered bool compares equal to both true and false, why?.
Does the C++ standard allow for an uninitialized bool to crash a program?
(Answering for C.)
But which unit or macro decides that it only can store 0 or 1?
In typical C implementations, the compiler implements this. The compiler decides (or is designed to) which instructions to use when manipulating _Bool values. It might test a _Bool with an instruction that sets a condition code according to whether the byte is zero or non-zero it might test it with an instruction that sets a condition code according to whether the low bit (for example) is zero or non-zero. The C standard does not impose any requirements on this. Each C implementation is free to choose its own implementation.
And what would happen if the value of a boolean type is accidentally modified in memory to a greater value?
This depends on the C implementation. A greater value might be treated as 1, if the implementation is testing zero versus non-zero. A greater value might be treated according to its low bit, if the implementation is using that. A greater value might behave differently in different circumstances, if the implementation uses varied instructions according to circumstances. A greater value also might cause results that would be otherwise nonsensical. For example, given int x = 4; and some _Bool y that has been inappropriately modified by writing to its memory, int z = x + y; might set z to 10 even though only 4 or 5 would be possible if y were a proper _Bool. When you modify the representation of a type to something other than bits that represent a proper value as defined by the implementation, the resulting behavior is not defined by the C standard, or, generally, by the C implementation.
Would it even be possible and permissible to assign a greater value to a boolean type?
No, assignments convert the right operand to the type of the assignment expression (which is the type of the left operand, except as a value rather than an lvalue).
Why do objects of the types bool and _Bool in C and bool in C++ can store only the values of 0 or 1 if they occupy 1 byte in memory which could hold 256 values?
Because, in the end, the language specification doesn't say how large a bool is, it only defines what it can do. The C language specification says that _Bool can hold a 0 or a 1. The size of a bool data type is a detail of individual implementations, not a part of the specification itself. It's possible to have an implementation that actually allocates individual bits for a bool, it's possible to have a specification that allocates multiple bytes for a bool. So to stay inline with the specification, the important part isn't the size of the memory allocated, but that it performs according to the specification which means it holds a 0 or a 1.
And what would happen if the value of a boolean type is accidentally modified in memory to a greater value since it can be stored in memory this way?
Undefined behavior I expect. I don't think that the specification says what happens, and as a result what happens is up to the implementor. One implementation may examine the first bit of the underlying memory and ignore the rest. Another implementation may examine the entire underlying memory location and if any of the bits are set, give a value of 1.
The word of caution...
You can write a program to see what your implementation does with such data and write programs that work will for your implementation, but know that you're not testing what 'C' does, you're testing what that particular implementation/compiler will do. Also, know that once you start treading into the waters of undefined behavior, you also start treading into the waters of things that will break programs for reasons that you may not understand. Compilers will apply a wide variety of optimizations based on a number of assumptions. The compiler may write a program that performs perfectly fine while you're doing a bunch of work, you finish it, you tell the compiler to create an optimized release version and because you've been digging into undefined behaviors you broke an assumption the compiler made and, it may apply an optimization that suddenly breaks your code and tracking it down may prove tremendously difficult. Always try to stick within well defined behaviors.
Why do objects of the types bool and _Bool in C and bool in C++ can store only the values of 0 or 1 if they occupy 1 byte in memory which could hold 256 values?
If bool can store the whole value range of a char then why don't just use char?
Of course, Their purpose is to represent only the values of 0 and 1 or true and false, but which unit or macro decides that it only can store 0 or 1?
The compiler will handle the conversion when you assign a value to a bool variable. If it's truthy then the variable will contains true. That behavior was defined in the C and C++ standards. That means bool a; a = 25; is completely valid and not "an inappropriate assignment" as you though. After that a will always contain true/1. You can never set a bool to anything other than 0 and 1 via normal variable assignment
There's no problem using a char or an int as bool like how it was before modern C and C++, but by limiting the value range it also allows the compiler to do a lot of optimizations. For example bool x = !y; will be done by a simple XOR instruction, which will not work if y contains any values other than 0 and 1. If y is a normal integer type then you'll need to normalize y to 0 and 1 first. See demo
As a matter of fact, not all bits in the representation have to involve in value calculation, and not all bit patterns have to be valid. C and C++ allow types to contain padding bits and trap representations, so a 32-bit type may have only 30 value bits, or be able to store only 232-4 different values. This is not to say that bool definitely contains padding bits, just a proof that you are permitted to have a type narrower than the possible range
The only exception we are aware of is _Bool (as observed by Joseph Myers wrt GCC). It seems one could either (a) take non {0,1} values to be trap representations in the current sense, or (b) regard operations on non {0,1} values of that type as giving an unspecified value. The latter would bound possible misbehaviour, which would be good for programmers; the only possible downside we are aware of is that it could limit compilation via computed branch tables indexed by unchecked _Bool values.
N2091: Clarifying Trap Representations (Draft Defect Report or Proposal for C2x)
However some implementations do consider them trap representations
In fact, as implemented by GCC and Clang, the _Bool type has two values and 254 trap representations.
Trap representations and padding bits - Pascal Cuoq
And what would happen if the value of a boolean type is accidentally modified in memory to a greater value?
If you manipulate the value of the bool to another value directly via a pointer then in C++ undefined behavior will happen
6.9.1 Fundamental types
Values of type bool are either true or false. 50 [Note: There are no signed, unsigned, short, or long bool types or values. — end note] Values of type bool participate in integral promotions (7.6).
50) 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.
C++17
I couldn't find the reference in C99 but it will be undefined behavior if the value you set is a trap representation
6.2.6 Representations of types
Certain object representations need not represent a value of the object type. If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined. If such a representation is produced by a side effect that modifies all or any part of the object by an lvalue expression that does not have character type, the behavior is undefined.41) Such a representation is called a trap representation.
There are already many questions regarding that "weird" behavior
_Bool type and strict aliasing
Setting extra bits in a bool makes it true and false at the same time
Why does bool and not bool both return true in this case?
Weird results for conditional operator with GCC and bool pointers
Engineered bool compares equal to both true and false, why?
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.
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.
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?!
If I have the following code:
int a = 1;
bool b = 1;
Does a equal to b? Even the program might return that they are the same, are they actually equal in all aspects in low level?
Also, if I use code (pseudo) such as:
if (a)
then execute();
will execute() run? I am asking for theoretical answers, and I can't convince myself with experiments as this is not natural science. Thank you all.
I think you can convince yourself with the right experiments:
#include <type_traits>
int main() {
int a = 1;
bool b = 1;
static_assert(! std::is_same<decltype(a), decltype(b)>::value,
"No, they are not the same on all aspects");
}
Perhaps the most important difference between the two is that bool can only have two values: true and false, while int can have many more. Here's another experiment that shows a consequence of this:
#include <cassert>
int main() {
int a = 2;
bool b = 2;
assert(a != b);
}
The two types may seem similar because there are implicit conversions between the two. Any integral expression that is zero can be implicitly converted to false, and any integral expression that is not zero can be implicitly converted to true. In the opposite direction, false can be implicitly converted to zero, and true converted to one. This leads to the code above ending up testing if 2 != 1.
Now the answer to the question of whether execute(); is called in the snippet from the question should be obvious: the value a will be converted to a bool in the if statement, and since it is not zero, it will convert to true and result in a call to execute().
A non-zero numerical or pointer expression will evaluate to true when used in a boolean context. Similarly, a zero expression will evaluate to false. However, an int and a bool are different types, so they are not the same.
Does a equal to b? Even the program might return that they are the same, are they actually equal in all aspects in low level?
It all depends on what you mean by equal. The type is different, and that means that the representation in memory will probably differ (the compiler is free to represent those two as exactly the same, but it is also free to do otherwise). In most compilers/architectures, bool takes just one byte of storage and int has a bigger size (usually 4 bytes, but this depends on the architecture).
Besides the different sizes, the compiler will treat both types differently (not just the loads and stores to memory, but also the operations will be different. You can only store 0 and 1 in a bool, and that means that some operations might use that knowledge. For example, in this article you will find one case where the implementation of the test of a condition differs (note, the article has a case of undefined behavior that causes a bool to evaluate to both true and false as for the test the compiler is assuming that the bool can only be either 0 or 1, that cannot happen with int)
From a logic point of view, the language determines how the different types are used in operations, and in particular if you try to compare a and b in your program, the result of the expression will be true. Note that it does not mean that they are exactly the same, the language defines a set of conversion rules that are used to transform both variables into the same type and the comparison is performed in that type. In this case the conversion will be to int. The bool variable will be converted to 0 if false or to 1 if true.
Also, if I use code (pseudo) such as: if (a) execute(), will execute() run?
Yes. In this case, the condition inside the if requires a bool value, so the conversion will be from int to bool. The standard defines that conversion to yield false if the integer value is 0, or true otherwise, effectively doing the equivalent of if (a!=0). Since a is 1, the condition holds and execute() will be evaluated.
This thread talks about c++ booleans in comparison to chars, but it'll give you a good idea of what's going on under the hood. Why is a char and a bool the same size in c++?