cprintfstring-formattingtinyosnesc

Strange behaviour of printf string format in C


I have the function below in nesCwhich is essentially same as C as far as I understood!

event void AdaptiveSampling.dataAvailable(error_t result, float val, bool isRealData)
{       
    if(result == SUCCESS)
    {
        //converting raw ADC to centigrade
        centiGrade = -39.60 + 0.01 * val;                       

        //printing the value to serial port
        if(isRealData)
        {
            printf("REAL: Temperature is: %d CentiGrade\r\n", centiGrade); //line 91
            printf("%d,R,%d,%d\r\n", _counter, val, centiGrade); //line 92
        }   
        else
        {
            printf("PEDICTED: Temperature is: %d CentiGrade\r\n", centiGrade); //line 96
            printf("%d,P,%d,%d\r\n", _counter, val, centiGrade); //line 97
        }   
        _counter++;     
    }
    else
    {
        printf("Error reading sensor!");
    }
}

And, at the top of my code I have defined these variables:

uint32_t _counter;
uint16_t centiGrade;

This is the warning I get during build:

AdaptiveSamplingC.nc:92:11: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘uint32_t’ [-Wformat]
AdaptiveSamplingC.nc:92:11: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘float’ [-Wformat]
AdaptiveSamplingC.nc:97:11: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘uint32_t’ [-Wformat]
AdaptiveSamplingC.nc:97:11: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘float’ [-Wformat]

And here is the example of output on screen:

PEDICTED: Temperature is: 26 CentiGrade
291,P,0,-3402
REAL: Temperature is: 26 CentiGrade
292,R,0,4096
PEDICTED: Temperature is: 26 CentiGrade
293,P,0,-1495

Problem:

In the line 91, I expect to see the temperature value to be float...I mean somethoig like 26.25...but for some reason it prints out as integer. I tried to change %d to %f but it didnt help as you see the output in line 92 and 97 are pretty much corrupted for a reason that I couldnt figure out yet!

Also I have no explanation why lines 92 and 97 behave that strange, and why do they have the warnings during the build time.

Would you kindly tell me what to do to improve?


Solution

  • Your problem is undefined behaviour, and that's why you're getting the warnings. Warnings are indications that something is actually wrong.

    printf is a variadic function, so it needs some information about the types of the arguments. That's the job of the format specifiers (eg. %d).

    %d tells printf to expect an int typed argument, which your warning messages are telling you: warning: format %d expects argument of type int

    However, the types you're giving it aren't ints. They're uint32_t and float, which your warning messages are also telling you: but argument 2 has type uint32_t [-Wformat] and but argument 3 has type float [-Wformat].

    There's a number of solutions. The best would be to use the correct format specifier! (duh). That's "%d" for int, "%"PRIu32 for uint32_t and "%f" for double (which floats get promoted to). In the case of uint32_t, you could cast to an unsigned long and print using "%lu", instead.