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 != NULL) { ++numWords; printf("Number of words is: %dn", numWords); println(tok); tok = strtok(NULL, " t"); } } 

我的问题围绕numWords的使用。 运行时系统是否重用此变量,或者每次运行for循环时是否分配新的int ? 如果你想知道我为什么这么问,我是一名Java程序员,他想要进入HPC,因此我想学习C.通常我知道你想避免这样的代码,所以这个问题真的是探索性的。

我知道答案可能依赖于编译器……我正在寻找一个更深层次的解释。 假设您选择的编译器。

    这就是C中所谓的“块”,“自动”或“局部”范围。它是词法范围的一种forms,即名称是指其本地环境。 在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 

    和:

     int g; // static by default and init to 0 extern int x; // defined and allocated elsewhere - resolved by the linker int main (int argc, const char * argv[]) { int j=0; // automatic by default while (++j<=2) { int i=1,j=22,k=3; // j from outer scope is lexically redefined for (int i=0; i<10; i++){ int j=i+10,k=0; k++; // k will always be 1 when printed below printf("INNER: i=%i, j=%i, k=%in",i,j,k); } printf("MIDDLE: i=%i, j=%i, k=%in",i,j,k); // prints middle j } // printf("i=%i, j=%i, k=%in",i,j,k); compiler error return 0; } 

    有特质:

    在您发布的特定示例中,您询问了int numWords = 0; 如果每次循环都分配一个新的int 。 不,在循环块中只分配了一个int,但每次都执行=的右侧。 这可以certificate:

     #include  #include  #include  volatile time_t ti(void){ return time(NULL); } void t1(void){ time_t t1; for(int i=0; i<=10; i++){ time_t t2=ti(); // The allocation once, the assignment every time sleep(1); printf("t1=%ld:%p t2=%ld:%pn",t1,(void *)&t1,t2,(void *)&t2); } } 

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

    现在与递归函数进行比较:

     int factorial(int n) { if(n <= 1) return 1; printf("n=%i:%pn",n,(void *)&n); return n * factorial(n - 1); } 

    n的地址每次都不同,因为每次递归调用都会分配一个新的自动n。

    与强制使用循环块分配的阶乘的迭代版本进行比较:

     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:%pn",result,(void *)&result); // address is always the same } return r; } 

    总之,你问过int numWords = 0; 在for循环中。 在此示例中重用该变量。

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

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

    另一方面,如果你每次通过循环调用Java中的new东西,那么是的,每次都会分配一个新对象。 但是,在这种情况下你不会这样做。 除非你调用malloc或类似的东西(或者用C ++, new ),否则C也不会从堆中分配任何东西。

    请注意automaticdynamic内存分配之间的区别。 在Java中只存在后者。

    这是自动分配:

     int numWords = 0; 

    这是动态分配:

     int *pNumWords = malloc(sizeof(int)); *pNumWords = 0; 

    C中的动态分配仅显式发生(当您调用malloc或其衍生物时)。

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

    从性能的角度来看,这并不重要。 (变量映射到寄存器或存储器位置,因此必须重复使用。)

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

    从逻辑的角度来看:

    numWords变量的范围在for循环中。 就像Java一样,你只能在循环中使用变量,所以理论上它的内存必须在退出时被释放 – 因为它在你的情况下也在堆栈中。

    但是,任何好的编译器都会使用相同的内存,只需在每次迭代时将变量重新设置为0。

    如果您使用的是class而不是int ,那么每次使用for循环时都会看到析构函数被调用。

    甚至考虑这个:

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

    这里创建的两个对象可能驻留在同一个内存中。

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

     for (i = 0; i < 100; i++) { int n = 0; printf("%d : %pn", i, (void*)&n); } 

    不保证所有100行都具有相同的地址(尽管可能会有)。

    编辑: 6.2.4 / 5中的C99标准说: "[the object] lifetime extends from entry into the block with which it is associated until execution of that block ends in any way." 并且,在6.8.5 / 5中,它表示for语句的主体实际上是一个块......所以第6.2.4 / 5段适用。

      以上就是c/c++开发分享C中的变量重用相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/545792.html

      (0)
      上一篇 2021年1月10日
      下一篇 2021年1月10日

      精彩推荐