C -静态变量被清除时调用sprintf



我有一个静态变量的问题,显示一些奇怪的行为。希望有人能帮助,这里是代码:

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以某种方式将其值更改为零。正如你在代码中看到的那样,它之前是1,但在sprint之后,我设置了一个断点,由于某种原因它是0。

如果我不通过注释它来使用sprintf,问题就会消失,变量的行为就会像预期的那样(不被清除,并在函数再次调用时保持值)。

sprint做错了什么吗?那么这个变量没有了?有什么想法吗?

这是在一个微控制器PIC16F1847上使用XC8编译器。由于

问题就在这里:

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

假设number = 0

sprintf()将"10000"加上字符串终止字符写入digits,共6个字符。然而,digits是一个只有五个字符的数组。在数组末尾之后写入会导致不可预测的结果。

char digits[5];重新定义为char digits[50];,或者一个足够大的值来容纳sprintf()函数的输出。

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

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

snprintf()函数不会写入超出数字数组大小的内容(像sprintf()那样)。相反,它将截断输出(如果有必要)以避免这样做。

这里的问题是char digits[5]。对sprintf的调用导致digits变量超出其边界,这意味着未定义的行为,从而导致有趣的事情发生!

选择使用更安全的呼叫snprintf,但要注意snprintf受到一些问题的影响,这些问题通过手册页明确。

最新更新