调用sprintf时静态变量被清除

时间:2014-05-27 02:28:31

标签: c static printf pic reentrancy

我遇到了一个显示一些奇怪行为的静态变量的问题。希望有人可以提供帮助,这是代码:

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; 

}

数字定义为char digits[5];

正如您所看到的,我正在定义一个本地静态变量,因此当多次调用此函数时,我可以跳转到程序的不同位置。

我刮胡子的问题出在第二行代码中。当sprintf被执行时,var digitenabled以某种方式将其值更改为零。你可以在代码中看到它之前的一个,但是在sprint之后我放了一个断点,由于某种原因它是零。

如果我不通过注释来使用sprintf,问题就会消失,变量会按预期运行(不清除并在再次调用该函数时保留该值。

sprintf做错了吗?所以变量消失了?任何想法?

这是在使用XC8编译器的微控制器PIC16F1847上。感谢

2 个答案:

答案 0 :(得分:5)

问题在于:

 char digits[5];   // from comment -jelipito

 sprintf(digits, "%d", number+10000);  // from question code.

假设number = 0。

sprintf()正在写“10000”加上一个字符串终止字符digits,总共6个字符。但是,数字是一个只有五个字符的数组。写入数组的末尾会导致不可预测的结果。

char digits[5];重新定义为char digits[50];,或者足以保存sprintf()函数输出的内容。

您可能考虑的另一个安全网是将sprint()替换为snprintf()

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

snprintf()函数不会超出数字数组的大小(就像sprintf()那样)。相反,它会截断输出(如果需要)以防止这样做。

答案 1 :(得分:1)

此处的问题是char digits[5]。对sprintf的调用导致digits变量超出其界限,这意味着未定义的行为反过来导致有趣的事情发生!

而是选择使用更安全的通话snprintf但请注意snprintf会受到通过手册页明确的一些问题的影响。