10

有没有办法重置函数中声明为静态的变量?目标是确保不会使用来自不相关调用的延迟值调用该函数。例如,我有一个对矩阵列进行操作的函数。

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
}
4

5 回答 5

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

于 2010-08-15T18:19:49.727 回答
0

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

于 2010-08-15T18:21:17.943 回答
0

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

于 2010-08-15T19:17:11.337 回答
0

如果需要一个可以命中未知数量的函数或模块的“重置”方法,有时可能会有帮助的一种方法是使用一个全局计数器来记录调用该重置方法的次数,然后让每个函数或模块包含代码如:

extern unsigned long global_reset_count;

void do_something(int 不管)
{
  静态的......这个,那个,另一个,等等......;
  静态无符号长 my_reset_count;

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

在一些多线程上下文中,如果静态变量的初始化可能依赖于一些全局变量,不妨将“if”替换为“while”;在这种情况下; 在这种情况下也可能需要内存屏障,但具体要求会因操作环境而异。

此外,在嵌入式系统中可能有用的另一种模式是modules_initialized通过全局重置方法将全局变量设置为 0,然后让每个模块以以下内容开头:

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

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

于 2012-01-19T17:17:15.067 回答
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 作为默认值

于 2017-02-28T09:03:01.707 回答