cstm8

Weird behavior of printf on a stm8l with COSMIC compiler


printf gives me weird extra values in some cases. What might be happening?

I'm manipulating values in an uint8_t array and printing it out to my terminal to verify if everything is correct. But for some reason I am getting weird values when I print a uint8_t - I get the expected value plus some other value (it is always the same extra value), as if I was printing a uint16_t or other 16bit value. I trimmed it all down to the following example:

This is the test code

test_payload[0] = (uint8_t)0x58;
test_payload[1] = (uint8_t)0x7B;
test_payload[2] = (uint8_t)0x6B;
test_payload[3] = (uint8_t)0x05;
test_payload[4] = (uint8_t)0x4F;
test_payload[5] = (uint8_t)0x81;
test_payload[6] = (uint8_t)0x69;
test_payload[7] = (uint8_t)0x00;

printf("%x\n\r", test_payload[0]);
printf("%x\n\r", test_payload[1]);
printf("%x\n\r", test_payload[0] + test_payload[1]);

for(i = 0; i < 8; i++)
{
    printf("%x", test_payload[i]);
}

The output I get is

5803
7b03
d3
58037b0333034f03810369033

What is making it behave like that?


Solution

  • The first code fragment should produce 58, but you do not output a newline, so any subsequent output will appear right after the 58. It is possible that you output 86 in the code that follows the fragment. Post a complete program that exhibits the offending behavior, or change the format as %x\n to separate 58 from subsequent output.

    Technically, printf expects an unsigned int argument for a %x conversion format, but an int value should work fine and test_payload[0] is promoted to int and passed as such to printf. You could try changing the format to %hhx or casting the argument as (unsigned int)test_payload[0], but it would be very surprising that one of these changes alone fix the problem.

    EDIT: from your extra information, it looks like the compiler for your embedded target is very peculiar. Definitely try casting the arguments as in

    printf("%x\r\n", (unsigned int)test_payload[0]);
    

    Observing that printf("%x\n\r", test_payload[0] + test_payload[1]); seems to work fine, the problem is not passing an int instead of an unsigned int, which would have been bad enough... It seems printf() passes uint8_t values incorrectly, in a non conforming way.

    Another potential source of problems is if you forgot to include <stdio.h> and are calling printf without a definition with a prototype. The C Standard (6.5.2.2 Function calls) explicitly defines this call as having undefined behavior if the function is defined (in the library) with a prototype that includes an ellipsis (...).