Сравнение подписанного и неподписанного символа

Это кажется таким странным. Я нашел недоразумение. Я использую gcc с char как подписанный char. Я всегда думал, что в выражениях сравнения (и других выражениях) знаковое значение при необходимости преобразуется в беззнаковое.

int a = -4;
unsigned int b = a;
std::cout << (b == a) << std::endl; // writes 1, Ok

но проблема в том, что

char a = -4;
unsigned char b = a;
std::cout << (b == a) << std::endl; // writes 0

что такое магия в операторе сравнения, если он не просто побитовый?