在C程序中,是否可以将所有全局变量重置为默认值?

时间:2010-09-13 22:22:51

标签: c global-variables

我有一个我需要重用的旧版C Linux应用程序。该应用程序使用了许多全局变量。我想重用这个应用程序的main方法并在循环中调用它。我发现当我在循环中调用main方法(重命名为callableMain)时,应用程序行为不一致,因为在上一次迭代中设置的全局变量值会影响新迭代中的程序流。

我想要做的是在执行新迭代之前将所有全局变量重置为默认值。

例如,原始程序就像这样

OriginalMain.C

#include <stdio.h>

int global = 3; /* This is the global variable. */

void doSomething(){     
         global++; /* Reference to global variable in a function. */    
}    

     // i want to rename this main method to callableMain() and
     // invoke  it in a loop 
     int main(void){    
       if(global==3) {    
       printf(" All  Is Well \n");    

       doSomething() ;  
     }
     else{

       printf(" Noooo\n");  

       doNothing() ;

     }
     return 0;
}

我想按如下方式更改此程序:

我更改了上面的文件,将main()重命名为callableMain()

我的新主要方法如下:

int main(){  

     for(int i=0;i<20;i++){  

         callableMain();

         // this is where I need to reset the value of global vaiables
        // otherwise the execution flow  changes
     }    
}   

是否可以在调用main()之前将所有全局变量重置为值?

简短的回答是,没有神奇的api调用会重置全局变量。全局变量必须被缓存和重用。

7 个答案:

答案 0 :(得分:8)

我会将其作为子进程调用,根据需要修改其输入和输出。让操作系统为你做脏事。

我们的想法是将遗留程序与新程序隔离开来,将其归入自己的程序。然后你们两者之间就分开了。此外,每次运行旧程序时都会将其重置为干净状态。

首先,修改程序,使其从文件中读取输入数据,并将其输出以机器可读的格式写入另一个文件,文件在命令行中给出。

然后,您可以创建命名管道(使用mkfifo调用)并使用system调用旧程序,并在命令行上传递命名管道。然后你输入它的输入并读回它的输出。

我不是这方面的专家;可能有更好的方法来进行IPC。这里的其他人提到fork。但是,分离遗留代码并将其作为子进程调用的基本思想可能是最好的方法。

答案 1 :(得分:5)

fork()早期?

当你认为全局状态处于良好状态时,你可以在某个早期点fork(2),然后让孩子在管道上等待某些工作要做。这需要将任何已更改的状态或至少结果写回父进程,但会将您的工作者与主要控制进程分离。

事实上,fork()至少两次可能是有意义的,一次设置一个工作控制器并保存初始化(但不是太初始化的:-)全局状态,然后让这个工作器控制器{{ 1}}再次为你需要运行的每个循环。

更简单的变体可能只是修改代码,以便进程可以以“工作模式”启动,然后使用fork()fork()在顶部启动应用程序,但是将其置于从模式的参数。

答案 2 :(得分:3)

有一种方法可以在某些平台/编译器上执行此操作,您基本上在调用main()之前执行编译器执行的相同初始化。

我已经为TI DSP做了这个,在这种情况下,我有一个全局变量映射到特定内存部分的部分,并且有可用的链接器指令声明指向本节开头和结尾的变量(所以你可以memset()在开始初始化之前整个区域为零)。然后,编译器提供了一个记录列表,每个记录包括一个地址,数据长度和要复制到地址位置的实际数据。所以你只需遍历记录并在目标地址中memcpy()来初始化所有全局变量。

特定于编译器,所以希望您使用的编译器允许您执行类似的操作。

答案 3 :(得分:1)

简而言之,没有。在这个例子中我要做的是创建定义,如果你愿意,然后使用它们来重置全局变量。

基本上

#define var1 10
int vara = 10
等等......基本C对吗? 然后,您可以继续将重新初始化包装在一个方便的函数中=)

答案 4 :(得分:0)

我认为你必须改变你看待问题的方式。

声明callableMain()内部的callableMain()所使用的所有变量,因此它们不再是全局变量,并且在执行该函数后被销毁,并在调用callableMain()时再次使用默认值创建下一次迭代。

修改

好的,如果你有callableMain()的源代码,你可以做什么:在函数的开头,添加一个检查来验证它是否第一次调用它的函数。在此检查中,您将所有全局变量的值复制到另一组 static 变量(根据需要命名)。然后,在函数体上用你创建的静态变量替换全局变量的所有出现。

这样,您将保留所有全局变量的初始值,并在callableMain()的每次迭代中使用它们。这对你有意义吗?

void callableMain()
{
  static bool first_iter = true;

  if (first_iter)
  {  
    first_iter = false;
    static int my_global_var1 = global_var1;
    static float my_global_var2 = global_var2;
    ..
  }

  // perform operations on my_global_var1 and my_global_var2, 
  // which store the default values of the original global variables.

}

答案 5 :(得分:0)

for (int i = 0; i < 20; i++) {
    int saved_var1 = global_var1;
    char saved_var2 = global_var2;
    double saved_var3 = global_var3;

    callableMain();

    global_var1 = saved_var1;
    global_var2 = saved_var2;
    global_var3 = saved_var2;
}

或许你可以找出全局变量从哪里开始memcpy。但是在开始循环时我总是会畏缩...

for (int i = 0; i < 20; i++) {
    static unsigned char global_copy[SIZEOFGLOBALDATA];
    memcpy(global_copy, STARTOFGLOBALDATA, SIZEOFGLOBALDATA);

    callableMain();

    memcpy(STARTOFGLOBALDATA, global_copy, SIZEOFGLOBALDATA);
}

答案 6 :(得分:0)

如果您不想重构代码并封装这些全局变量,我认为您可以做的最好的事情是定义一个重置函数,然后在循环中调用它。