Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中的变量重用_C - Fatal编程技术网

C语言中的变量重用

C语言中的变量重用,c,C,我看到的代码是: for (i = 0; i < linesToFree; ++i ){ printf("Parsing line[%d]\n", i); memset( &line, 0x00, 65 ); strcpy( line, lines[i] ); //get Number of words: int numWords = 0; tok = strtok(line , " \t"); while (tok !

我看到的代码是:

for (i = 0; i < linesToFree; ++i ){
    printf("Parsing line[%d]\n", i);

    memset( &line, 0x00, 65 );
    strcpy( line, lines[i] );

    //get Number of words:
    int numWords = 0;

    tok = strtok(line , " \t");
    while (tok != NULL) {
        ++numWords;
        printf("Number of words is:  %d\n", numWords);
        println(tok);

        tok = strtok(NULL, " \t");
    }
}
for(i=0;i
我的问题集中在
numWords
的使用上。运行时系统是否重用此变量,或者每次运行
for
循环时是否分配新的
int
?如果你想知道我为什么要问这个问题,我是一个Java程序员,我想进入HPC,因此我想学习C。通常我知道你想避免这样的代码,所以这个问题是一个探索性的问题


我知道答案可能取决于编译器。。。我在寻找比这更深刻的解释。假设您选择的编译器

从性能的角度来看,这无关紧要。(变量映射到寄存器或内存位置,因此必须重用。)

从逻辑的角度来看,是的,它将被重用,因为您在循环之外声明了它

从逻辑的角度来看:

  • numWords
    不会在外部循环中重用,因为它是在内部声明的
  • numWords
    将在内部循环中重新使用,因为它没有在内部声明

请注意
自动
动态
内存分配之间的区别。在Java中,只有后者存在

这是自动分配:

int numWords = 0;
int *pNumWords = malloc(sizeof(int));
*pNumWords = 0;
int fac2(int num) {
    int r=0;   // needed because 'result' goes out of scope
    for (unsigned int i=1; i<=num; i++) {
        int result=result*i;   // only RH is executed after the first time through
        r=result;
        printf("result=%i:%p\n",result,(void *)&result);  // address is always the same
    }
    return r;
}
这是动态分配:

int numWords = 0;
int *pNumWords = malloc(sizeof(int));
*pNumWords = 0;
int fac2(int num) {
    int r=0;   // needed because 'result' goes out of scope
    for (unsigned int i=1; i<=num; i++) {
        int result=result*i;   // only RH is executed after the first time through
        r=result;
        printf("result=%i:%p\n",result,(void *)&result);  // address is always the same
    }
    return r;
}
C中的动态分配只显式发生(当您调用
malloc
或其衍生物时)


在您的代码中,只有值被设置为您的变量,没有分配新的变量。

您关于这在Java中如何工作的概念可能是错误的-Java也不会每次通过这样的循环“分配”一个新的
int
。像
int
这样的基本类型变量不在Java堆上分配,编译器将为每个循环迭代重用相同的本地存储


另一方面,如果每次通过循环调用Java中的
new
任何东西,那么每次都会分配一个新对象。但是,在这种情况下,您没有这样做。C也不会从堆中分配任何东西,除非你调用<代码> MalOC 或类似(或C++,<代码>新< /COD>)。正如Java一样,您只能在循环中使用变量,因此理论上,它的内存必须在退出时释放,因为在您的情况下,它也在堆栈中

然而,任何好的编译器都会使用相同的内存,并在每次迭代时将变量重新设置为0

如果使用的是
类而不是
int
,则每次
for
循环时都会调用析构函数

甚至考虑这一点:

class A;

A* pA = new A;
delete pA;
pA = new A;

此处创建的两个对象可能位于同一内存中。

它将在每次循环中分配(编译器可以优化该分配)

(i=0;i<100;i++)的
{
int n=0;
printf(“%d:%p\n”,i,(void*)&n);
}
不保证所有100行都有相同的地址(尽管可能会)

编辑:在6.2.4/5中说:
“[对象]的生存期从进入与其关联的块开始,一直到该块的执行以任何方式结束。”
,在6.8.5/5中,它说
for
语句的主体实际上是一个块。。。因此,第6.2.4/5段适用。

这就是C中所谓的“块”、“自动”或“本地”范围。它是一种形式,即名称指其本地环境。在C语言中,它是自顶向下的,这意味着它发生在文件被解析和编译时,并且只有在程序中定义之后才可见。 当变量超出范围时,词法名称不再有效(可见),内存可能会被重用

变量在局部范围或由大括号
{/*block*/}
定义的块中声明。这定义了一组完整的C和C99习惯用法,例如:

for(int i=0; i<10; ++i){    // C99 only. int i is local to the loop
    // do something with i 
}  // i goes out of scope here...
 int x = 5;
 int y = x + 10; // this works

 int x = y + 10;
 int y = 5;      // compiler error     
以及:

使用任何与gcc(clang、eclipse等)兼容的编译器,在优化关闭(
-O0
)或打开的情况下编译它。t2的地址将始终相同

现在与递归函数比较:

int factorial(int n) {
    if(n <= 1)
        return 1;
    printf("n=%i:%p\n",n,(void *)&n);
    return n * factorial(n - 1);
}
总之,您询问了
int numWords=0在for循环中本例中重复使用该变量。


代码的编写方式,程序员依赖于
int numWords=0的RH在第一次执行后,将变量重置为0,以便在随后的while循环中使用

当控件位于定义numwords的循环中时,numwords被重用;当控件从循环中传递出去时,numwords就不存在了。但是在
for
循环中,它会像在Java中那样被“重新声明”还是被重用?与Java不同,Java中的对象声明意味着动态资源分配,C中拼写int i只意味着“将变量存储在某处”(带有“某处”)实际上是在堆栈上,而不是在动态分配的内存池中)。但是是的,它是重新声明的,因为您不能期望它在迭代之间保存它的值。它可以保存它的状态,但前提是该特定内存地址不会被另一个完全随机的变量覆盖。C中的“声明”只告诉编译器在堆栈或寄存器中为它保留空间。因此,没有真正的“重新定义”概念。@VioletGiraffe:Java不会为primiti的变量进行任何动态资源分配