Hi all, recently I have discovered some errors in the boolean data type. I have posted an issue to GitHub which also contains a fix, however for community awareness
I have started this thread to discuss the issue.
Also if anybody does not understand why the boolean type is unsafe to use, or just want a clearer explanation please feel free to ask.
The website and forum section does not have much action, so hopefully many people will have the chance to see this.
If a mod feels its better in the suggestions for the Arduino project forum, then feel free to move it.
First up, don't worry newbies, simply use bool instead of boolean in your code, problem solved.
The boolean alternative should only be used in C code.
The main problem stems from the fact, that integer conversions are unlike boolean conversions; and boolean is actually defined as an unsigned 8 bit integer ( uint8_t ), not a bool. Therefore it is subject to integer conversions which the standard describes follows ( only copied info for unsigned destination, which is what a boolean is ).
4.7 Integral conversions [conv.integral]
2 If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source
integer (modulo 2
n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s
complement representation, this conversion is conceptual and there is no change in the bit pattern (if there
is no truncation). — end note ]
Where the boolean type conversion is as follows
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.
This all breaks down as true and false are subject to integral promotion, and the standard says:
A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true
becoming one.
So when we assign a 5 to a boolean, we'd expect it to convert to true, however the code below returns false.
true == boolean( 5 );
This is because the code is actually running the equivalent of this snippet ( after integral promotion ).
uint8_t( 1 ) == boolean( 5 );
Which is clearly false.
All except one of these conditions should be true using boolean logic, your Arduino will beg to differ!
void setup() {
Serial.begin(9600);
Serial.println( true == (bool) 57 ? "true" : "false" );
Serial.println( true == (boolean)57 ? "true" : "false" );
Serial.println( true == bool( true ) ? "true" : "false" );
Serial.println( bool( 1 | 2 | 4 | 8 ) == boolean( 1 | 2 | 4 | 8 ) ? "true" : "false" );
Serial.println( true == false + 1 ? "true" : "false" );
Serial.println( true + true == true ? "true" : "false" );
Serial.println( bool( true + true ) == true ? "true" : "false" );
Serial.println( boolean( true + true ) == true ? "true" : "false" );
}
void loop(){}
Also the actual Arduino reference makes claims which I have just proven otherwise.
"A boolean holds one of two values, true or false." and "Any integer which is non-zero is true ( in a boolean sense )."
As I have clearly shown that: "true != (boolean)57" their quotes above are only true for the real standard bool.
Their specific Arduino conventions truly are defining a new language. I also motion to remove the #defines for true and false ( at least for the C++ side of things ).
Note: the standard explicitly disallows #defining keywords:
17.4.3.1.1 Macro names [lib.macro.names]
... Nor shall such a translation unit define macros for names lexically identical to keywords.
I'm still working on a proof for why true and false defines should be dropped, however the statement above should seal the deal.
I have replied below with some code that is not using a boolean comparison, it should be good enough proof that the data type needs to be removed.
One way to make code safe when using boolean is to double negate the contents.
boolean b = !!57;
Now you can guarantee that b is either 0 or 1 as 57 has been through a real boolean conversion.
Here is one last example which may clearly show the lack of boolean conversion:
void setup() {
Serial.begin(9600);
bool arr1[6];
boolean arr2[6];
arr1[0] = arr2[0] = 'H';
arr1[1] = arr2[1] = 'e';
arr1[2] = arr2[2] = 'l';
arr1[3] = arr2[3] = 'l';
arr1[4] = arr2[4] = 'o';
arr1[5] = arr2[5] = 0;
Serial.print( "Printing bool array: " );
Serial.println( ( char* ) arr1 );
Serial.print( "Printing boolean array: " );
Serial.println( ( char* ) arr2 );
}
void loop(){}
Some of this text I have pieced together from other pages, hopefully its presented understandably. The GitHub issue has additional info, however ask away if questions are brewing. boolean data type causes logic errors. · Issue #2147 · arduino/Arduino · GitHub