# Why char 0x80 == 0xFFFFFF80?

As far as I know a char is an 8 bit variable ``````void setup() {
Serial.begin(9600);
}

void loop() {
char x = 0x80;
if(x != 0x80){
Serial.println(x, HEX);
}

delay(1000);
}
``````

To illustrate the reasons better let's look at the actual content of the data.

`0x80` is `0b10000000` in binary. A `char` is a signed variable, which means that the most significant bit is the sign bit, with two's complement representation

So in 8-bit signed representation the value `0b10000000` is a sign bit and zero value - which is -128 in decimal notation, which is "-128 + the 7 least significant bits", or -128 + 0 in this case.

When you print a signed value on the Arduino as HEX there is no 8-bit specific function for it. Neither is there a 16 bit function. However there is a 32-bit signed function, which is the closest match available. So the compiler performs type promotion to 32-bit signed, then represent it as hexadecimal.

Now -128 in signed 32-bit is calculated in the same way - take the value of the most significant bit, negate it, and add the value of all the other bits to it. With 32-bits the value of the most significant bit, in decimal, is 2147483648, so negate that into -2147483648. Now we need to make that into -128, so we need the difference between the two to add to it. That's 2147483520.

So you get the MSB + 2147483520, which in hexadecimal, is 0xFFFFFF80.

Of course, the compiler doesn't go through that whole routine - instead it uses something called sign extension. This method basically means copying the sign bit from the original smaller (char) type into every bit to the left of it in the larger type:

``````                           10000000 8 bit signed
11111111 10000000 16 bit signed
11111111 11111111 11111111 10000000 32 bit signed
``````

All those are -128 in two's complement, just stored in different size variables. So when you come to print it, that is just what you get - the two's complement representation of -128 in the variable size that has been accepted by the print function.

You might find this site useful for experimentation and furthering your understanding of variable data storage.

char is signed so `0x80` is really `-0x80` (`==-128`). When promoted to a higher width the sign gets copied into the new bits `0xffffff80` (still `==-128`).

if you put unsigned in front of char you won't get that issue (though may encounter others).

``````void setup() {
Serial.begin(9600);
}

void loop() {
unsigned char x = 0x80;
if(x != 0x80){
Serial.println(x, HEX);
}

delay(1000);
}
``````

Sign extension. Try this:

``````void loop() {
char x = 0x80;
if(x != (char) 0x80){
Serial.println(x, HEX);
}
``````

Before any operation involving different types, the lower ones must be promoted to higher ones.

The constant 0x80 is an integer value, so `x` must be promoted to `int` before the test. The first bit of an `int` value is the sign bit. Sign bit is extended (copied to the left side bits). So `x` become 0xFFFFF80 and then you compare it against 0x0000080.

Every time you put a char where an int is excepted the same thing happen.

See? Programming is hard, programming in C is harder, programming in C++ is the hardest.

C is full of traps.