Search code examples
cstaticprintfpicreentrancy

static variable getting cleared when calling sprintf


i am having an issue with a static variable that is showing some odd behavior. Hopefully someone can help, here is the code:

void digitRefresh(void){

static char digitenabled=1;

sprintf(digits, "%d", number+10000);

switch (digitenabled) {
    case 1: digitDecode(digits[1] - 48);
        CATHODE_1 = ENABLE;
        break;
    case 2: digitDecode(digits[2] - 48);
        CATHODE_2 = ENABLE;
        break;
    case 3: digitDecode(digits[3] - 48);
        CATHODE_3 = ENABLE;
        break;
    case 4: digitDecode(digits[4] - 48);
        CATHODE_4 = ENABLE;
        break;
}
delay_ms(DIGIT_DELAY);

disableAllCathodes();
return; 

}

by the way digits is defined as char digits[5];

As you can see i am defining a local static variable, so when this function is called multiple times, i can jump into the different places of the program.

The problem that i shave is in the second line of code. When the sprintf gets executed the var digitenabled somehow changes its value to zero. It was one before as you can see in the code, but after the sprint i put a breakpoint and it is a zero for some reason.

If i don't use sprintf by commenting it out, the problem goes away and the variable behaves as expected (not cleared and keeps the value when the function is called again.

Is sprintf doing something wrong ? so the variable is gone ? any ideas ?

this is on a micro controller PIC16F1847 using XC8 compiler. Thanks


Solution

  • The problem is here:

     char digits[5];   // from comment -jelipito
    
     sprintf(digits, "%d", number+10000);  // from question code.
    

    Assume the number = 0.

    The sprintf() is writing "10000" plus a string termination character to digits, 6 characters total. However digits is an array of only five characters. Writing past the end of an array causes unpredictable results.

    Redefine char digits[5]; to char digits[50];, or something that is large enough to hold the output of the sprintf() function.

    Another safety-net you might consider is to replace sprint() with snprintf():

     snprintf(digits, sizeof(digits), "%d", number+10000);
    

    The snprintf() function will not write beyond the size of the digits array (like sprintf() does). Rather, it will truncate the output (if necessary) to keep from doing so.