I was trying to use the bitwise NOT ( ~ ) to flip a bit for every iteration of a loop. But it does not work as expected whereas the bitwise XOR ( ^) works. See code below - I know I am making a mistake but not sure what...
void loop(void)
{
bool static LED_State = 0;
LED_State = 1^LED_State ; // This blinks the LED.
//LED_State = ~LED_State ; // This does not blink the LED
digitalWrite( Ch1_OKLed, LED_State);
delay(500);
}
LED_State = (byte) ~LED_State ; // Why does it have to be cast ?
While using the Keil compiler for the 8051 MCU, following statement was quite valid for the "bit" variable type ( which i think is equivalent to the boolean ?)
bit LED_State = 0;
LED_State = ~LED_State ;
Just raising this since both Arduino IDE and Keil IDE are compatible with C .
Where value is either HIGH or LOW.
The API is not defined to allow value to be anything else like zero/non-zero or 0/1
While currently the values of HIGH and LOW happen to be 1 and 0, they are not require not require to be those values. So to take advantage of that internal implementation knowledge is abusing the API since the API function is defined as using HIGH or LOW and the behavior of any other value is undefined.
Also, depending on the implementation of the digitalWrite() code, the code may check for LOW or HIGH and default to assuming the other.
i.e. if the code checked for LOW then any non-zero value would work instead of HIGH to create a high level pin output.
However, if the code checked for HIGH then a high level output would only be achieved for the single value of HIGH and any other value like zero or any other non zero value would result in a low pin.
This is why taking advantage of internal implementation knowledge is bad programming practice that should be avoided when possible.
The proper way to handle this would be use only use HIGH and LOW and then use something like an inline ternary to set the value based on value of LED_State.
i.e.
modify your LED_State variable any way you want that creates a zero/non zero value, then use:
digitalWrite(ledPin, LED_State ? HIGH : LOW);
which ensures that only HIGH and LOW are ever used as the value parameter.
if x is declared as a "bool", then both "x = ~True" and "x = ~False" evaluate to "True." The compiler notices this, and produces no code that actually toggles the value. It will work fine if the LEDState is byte or integer.
(~ 0 is 0xFF, which evaluates to True (1) when assigned to a bool.
~1 is 0xFE, which evaluates to True (1) when assigned to a bool.
You wouldn't get this behavior in, say, a C program that typedef'ed a "bool" as a synonym for "byte" or something, but C++ has bool as a distinct type.)
Using bitwise negate on a boolean makes about as much sense as using it on a float..... Never make assumptions about the implementation of undocumented features in a language. It's just begging for trouble. Use the language as documented, and you'll very rarely have problems.
Patient: "Doctor, it hurts when I do this."
Doctor: "Then don't do that!"
It IS documented (see the stackoverflow link.) It promote to an int, does the bitwise operation, and then the assignment converts back to a bool (0 or 1, only.)
Thanks to all those who posted to clarify ... there were some hints to never do undocumented things. Sadly most time the problem is "I do not know that I do not know !! "
The explanations by pberrybap and westfw were in particular easy to follow.
And I couldn't help smile when I replaced "do this" and "do that " by "walk" in Doctor -Patient conversation !!
westfw:
It IS documented (see the stackoverflow link.) It promote to an int, does the bitwise operation, and then the assignment converts back to a bool (0 or 1, only.)
digitalWrite is documented to take either LOW or HIGH as the value argument. Passing a byte with any other value is undocumented. It might, or might not, accept either 0x01 and/or 0xfe as the same thing as HIGH, and might, or might not, accept 0x00 and/or 0xfe as the same thing as LOW.
In any case, doing bitwise negate on a boolean is just dumb. That si what logical negate is for.