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的变量进行任何动态资源分配