Bitwise not on a byte with highest bit a 1 behaves in the way I expect.
The inverted byte is 255 minus byte.
I can use it in char = (char)inverted byte and gives me an ascii character.
When I use a byte with highest bit a 0 the inverted byte is also 255 minus byte.
But when I want to use that inverted byte in char = (char)inverted byte I get a negative number.
The output of the sketch that I post here illustrates that.
myByte =: 128
bitwise not myByte is: 127
myChar = (char)temp; is: 127
myByte =: 208
bitwise not myByte is: 47
myChar = (char)temp; is: 47
myByte =: 127
bitwise not myByte is: 128
myChar = (char)temp; is: -128
myByte =: 33
bitwise not myByte is: 222
myChar = (char)temp; is: -34
Maybe I don't understand well enough the idea of typecasting.
Maybe a byte is not always unsigned.
Maybe ...... you know the right answer.
byte myByte;
char myChar;
byte temp;
void setup() {
Serial.begin(115200);
}
void loop() {
printMyByte(128); //proces myByte
printMyByte(208);
printMyByte(127);
printMyByte(33);
while (true);//wait for ever
}
void printMyByte( byte myByte) {
Serial.print("myByte =: ");
Serial.println(myByte, DEC);
temp = ~myByte;//temp is bitwise not myByte
Serial.print("bitwise not myByte is: ");
Serial.println(temp, DEC);
myChar = (char)temp;//myChar is inverted myByte typecasted as a char
Serial.print("myChar = (char)temp; is: ");
Serial.print(myChar, DEC);
Serial.print("\n\n");
}
A char is signed, a byte is not.
On the right side of an equal sign, variables are converted to 16 bit int (or higher) PRIOR to arithmetic.
Conversion from 16 bits to 8 bits across the equal sign may be a simple truncation.
Think bits, not decimal values.
I do not know what "bites" is. Bits? Bytes?
Why 8 bit quantities went to 7 bits I do not know.
myChar is declared as char and is ALWAYS 8 bits, NEVER 32 bits.
Printing a negative value as 32 bits (or 8 nibbles in hex) is an artifact of how the Print object prints a 'char' when you specify a base. There is no "Print::print(char c, int base)" so the 'char' gets promoted to an 'int' (with the requisite sign extension) and the call is made to:
size_t Print::print(int n, int base)
{
return print((long) n, base);
}
When the 'int' is cast to 'long' the sign extension is extended to 32 bits.
If you cast your char to 'unsigned char' (a.k.a. 'byte') before you print it as binary or hex you will get the proper effect.
What they can add to eliminate this confusing artifact is:
size_t Print::print(char c, int base)
{
if (base == 10)
return print((long) c, base);
else
return print((unsigned long) (unsigned char) c, base); // Prevent sign extension for binary and hex
}
and
size_t Print::print(int n, int base)
{
if (base == 10)
return print((long) n, base);
else
return print((unsigned long) (unsigned int) n, base); // Prevent sign extension for binary and hex
}