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

时间:2010-08-15 18:14:46

标签: c static initialization reset

有没有办法重置函数中声明为static的变量?目标是确保不使用来自不相关调用的延迟值调用该函数。例如,我在矩阵的列上有一个函数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被调整大小并归零等。似乎最简单的方法是使用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
}

5 个答案:

答案 0 :(得分:3)

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

例如:

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变量,而是使用传入的新函数返回/写入并传递给后续的相关调用。< / p>

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

extern unsigned long global_reset_count;

void do_something(int whatever)
{
  static ... this, that, the other, etc. ...;
  static unsigned long my_reset_count;

  if (my_reset_count != global_reset_count)
  {
    my_reset_count = global_reset_count;
    ... initialize this, that, the other, etc ...
  }  
}

在某些多线程上下文中,如果静态变量的初始化可能依赖于某些全局变量,则可能希望用“while”替换“if”;在这种情况下;在这种情况下也可能需要记忆障碍,但具体要求会因操作环境而异。

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

  if (!atomic_bit_test_and_set32(&modules_initialized, FOOBOZZ_MODULE_ID))
  {
    ... Initialize module FOOBOZZ ...
  }

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

答案 4 :(得分:0)

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

这是一个例子:

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作为默认值