本节书摘来自华章计算机《编写高质量代码:改善c程序代码的125个建议》一书中的第1章,建议9,作者:马 伟 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
建议9:尽量不要在可重入函数中使用静态(或全局)变量
前面介绍过,静态变量的存储方式与全局变量一样,都是静态存储方式。因此,在使用全局变量、静态变量的函数时,需要考虑重入问题。所谓的可重入函数是指函数可以由多于一个的任务并发使用,而不必担心数据错误。反之,不可重入函数不能由超过一个的任务所共享,除非能够确保函数的互斥性(或者使用信号量,或者在代码的关键部分禁用中断)。
来看一个不可重入函数的示例,代码如下所示:
size_t sum_index( size_t index )
{
size_t i;
static size_t sum=0;
for (i = 1; i <= index; i++)
{
sum += i;
}
return sum;
}
上面的sum_index函数之所以是不可重入的,就是因为函数中使用了static变量。前面已经阐述过,静态局部变量是在编译时赋初值的,且只赋初值一次,在程序运行时它已有初值。以后在每次调用函数时不再重新赋初值,而是保留上次函数调用结束时的值。所以,这样的函数又被称为带“内部存储器”功能的函数。
函数sum_index的调用示例如下:
int main(void)
{
printf("%d\n",sum_index(1));
printf("%d\n",sum_index(2));
printf("%d\n",sum_index(3));
}
运行结果如图1-44所示。
由于全局变量与静态变量一样,都是静态存储方式,因此,它同样可以导致不可重入函数,如下面的代码所示:
size_t g_sum = 0;
size_t sum_index( size_t index )
{
size_t i;
for (i = 1; i <= index; i++)
{
g_sum += i;
}
return g_sum;
}
因此,如果需要一个可重入的函数,那么一定要尽量避免使用static变量与全局变量,能不用则尽量不用。当然,有些时候在函数中是必须使用static变量的,比如当某函数的返回值为指针类型时,则必须以static局部变量的地址为返回值,若为auto类型,则返回为错指针。
如果我们需要将上面的函数修改为可重入的函数,其实也很简单,只要将声明sum变量中的static关键字去掉,将变量sum变为一个auto 类型的变量,函数即可变为一个可重入的函数。如下面的代码所示:
size_t sum_index( size_t index )
{
size_t i;
size_t sum=0;
for (i = 1; i <= index; i++)
{
sum += i;
}
return sum;
}