如何重置函数内的静态变量

有没有办法重置函数中声明为static的变量? 目标是确保不使用来自不相关调用的延迟值调用该函数。 例如,我有一个矩arrays的函数opearting。

int foo(matrix *A, int colnum, int rownum){ static int whichColumn; static int *v; //vector of length A->nrows if (column != whichColumn){ memset(v,0,size); whichColumn = which; } //do other things } 

该函数被调用n次,每列一次。 这是“重新设置”静态变量的正确方法吗? 是否有其他一般的万无一失的重置静态变量的方法? 例如,我想确保如果使用可能具有不同维度的新矩阵进行调用,则向量v被resize并归零等。似乎最简单的方法是使用NULL指针调用该函数:

 int foo(matrix *A, int colnum, int rownum){ static int whichColumn; static int *v; //vector of length A->nrows if (A == NULL){ FREE(v); whichColumn = 0; } //do other things } 

我建议把它变成一个结构并编写一个小辅助函数来管理你想要做的事情的语义。 如果请求适合其大小,它可以返回缓冲区,或者如果需要,可以根据需要创建新缓冲区(并释放旧的)。

请改用幂等初始化函数和全局变量。

例如:

 int foo; int *m = NULL; static void InitVars() { foo = 0; if (m != NULL) { free(m); } m = malloc(sizeof(int)*5); memset(m, 0, sizeof(int)*5); } 

如果初始化程序确实是幂等的,则可以再次调用它来重置变量。

如果您需要自动调用它,请使用__attribute__((constructor)) (对于GCC),如下所示:

 static void InitVars __attribute__((constructor)) (); 

但是,您应该注意,如果您需要这样做,您应该重新考虑使用函数内的static变量,而是使用传入的新函数返回/写入并传递给后续的相关调用。

我将C模块导入C ++时使用的一种方法是使用类包装器包围整个模块,并将函数内的所有静态变量替换为函数外部唯一命名的“全局”变量。 我不知道为涉及多个源文件的项目实现类似效果的任何好方法,但我想知道是否存在。 我在C中有一些嵌入式系统代码,我通过在VS2005中添加一些C ++包装器来模拟。 例如,我定义了I / O寄存器,以便TX1CON = 0x5C; 将翻译成IOMAP(0x251).P = 0x5C; IOMAP是一个将“写入0x5C到地址0x251”发送到硬件仿真程序的属性。 这种方法效果很好,但我不能做一个干净的重置。 有任何想法吗?

如果需要一个可以触及未知数量的函数或模块的“重置”方法,有时可能有用的方法是有一个全局计数器,用于调用重置方法的次数,然后让每个函数或模块包括代码如:

 extern unsigned long global_reset_count;

 void do_something(int whatever)
 {
  静......这个,那个,另一个......等等;
   static unsigned long my_reset_count;

   if(my_reset_count!= global_reset_count)
   {
     my_reset_count = global_reset_count;
     ...初始化这个,那个,另一个,等等......
   }  
 }

在一些multithreading上下文中,如果静态变量的初始化可能依赖于某些全局变量,则可能希望用“while”替换“if”; 在这种情况下; 在这种情况下也可能需要存储器屏障,尽管确切的要求会根据操作环境而变化。

此外,在嵌入式系统中可能有用的替代模式是将一个modules_initialized全局变量通过全局重置方法设置为0,然后让每个模块以类似于:

   if(!atomic_bit_test_and_set32(&modules_initialized,FOOBOZZ_MODULE_ID))
   {
     ...初始化模块FOOBOZZ ......
   }

这将要求不超过32个模块ID,并且要求它们以某种方式唯一地分配,但是一些系统可以很好地处理它。 例如,链接器可以允许从地址空间的地址0-31定义“数据部分”,而不依赖于任何其他地址空间。 如果每个模块在该地址空间内声明一个单字节变量,则链接器可以为这些变量生成适当的地址。

你可以用这样的方式构建你的函数,如果你用零参数调用它,那么它将重置它的内部静态变量

这是一个例子:

 int foo(matrix *A = NULL, int colnum = 0, int rownum = 0) { static int whichColumn; static int *v; //vector of length A->nrows if (A == NULL){ FREE(v); whichColumn = 0; } //do other things } 

你实际上只需调用函数重置如下:

 foo(); // internal values would then be reset 

确保函数的所有参数都具有默认值,例如,如果传递了一个可选参数,则确保它具有= boost :: none作为默认值