Как было сказано ранее, использование 'i' в качестве спецификатора формата некорректно для переменной типа unsigned char.
Всякий раз, когда вы не знаете, какой правильный форматдля любого конкретного (целочисленного) типа, вы можете просто взглянуть на inttypes.h, который содержит набор макросов, предназначенных для использования в переносимых строках формата.В зависимости от платформы, для которой вы разрабатываете, правильные спецификаторы формата могут отличаться (например, uint16_t может быть 'u' или 'hu', int32_t может быть 'd' или 'ld').
Вы можетелибо используйте этот заголовок как «шпаргалку», либо фактически напишите свои строки формата следующим образом:
printf("a=%"PRIu32"\nb=%"PRIu8"\n", a, b);
Обратите внимание, что для того, чтобы код был действительно переносимым, вам, конечно, также нужно использовать uint8_t вместоchar без знака и uint32_t вместо int.