A signed int is signed, an unsigned int is unsigned. If you use just int, it implies signed int. Same is true for short, long or long long. Yet it isn't true for char. A signed char is signed, an unsigned char is unsigned, but just char may be either signed or unsigned. The data type char is supposed to hold a "character", hence the name, so it's not "really" an integer type to hold an integer number to be used in calculations. Of course a character is in reality an integer of some kind but of which kind is implementation dependent (the C standard does not force any specific kind). So if you want to use the char type for integer values (also used in calculations), always use signed char or unsigned char explicitly and only use just char when you are really dealing with characters or when it makes absolutely no difference for your code if char is signed or unsigned.
The comparison fails because your implementation defines char to be in fact signed char, so you are comparing a signed char to an unsigned char in your final if statement. Whenever you are comparing two integers of different type, the compiler converts both values to the same type according to the rules of the C standard before it actually performs the comparison. In your case, this means the C compiler actually does tho following:
if((int)a==(int)b) printf("equal\n");
else printf("not equal\n");
}
And now it should be obvious why those two values don't match. (int)a has a value of -1, however (int)b has a value of 255, and these two values are not equal.
According to the rules of type promotion, char (in your case signed) is promoted to int and unsigned char is also promoted to int. The ISO C 2011 standard says:
If an int can represent all values of the original type (as restricted
by the width, for a bit-field), the value is converted to an int;
otherwise, it is converted to an unsigned int. These are called the
integer promotions.) All other types are unchanged by the integer
promotions.
The integer promotions preserve value including sign. As discussed
earlier, whether a ‘‘plain’’ char is treated as signed is
implementation-defined.