2009-11-06 94 views
10

我对下面的C代码的问题:何时为本地变量分配堆栈空间?

void my_function() 
{ 
    int i1; 
    int j1; 

    // Do something... 

    if (check_something()) 
    { 
     int i2; 
     int j2; 

     // Do something else... 
    } 

    // Do some more stuff... 
} 

是否存在时,堆栈空间分配/释放的I2和J2或者它依赖于编译器有关的任何担保?我希望当i2和j2进入作用域时调整堆栈指针,并在超出作用域时将其调整回去,但后来认为一些编译器可能只是“优化”整个事物并解释嵌套作用域中的变量该功能首先输入。

我知道我可以看看我的编译器生成的汇编代码,但想知道实现是否可以留给编译器。

谢谢!

+5

还要考虑变量可以分配给寄存器... – unwind 2009-11-06 15:17:41

回答

6

只要该语言的语义保留,编译器就可以随心所欲地做任何事情。换句话说,i2j2可以在执行到达其块的入口点之前被绑定到内存位置,并且只要不影响代码的语义,它可以在任何时候都是无限的。

8

没有保证。

不同的优化标志可能会导致不同的方法保存变量。

编译器甚至可以让一个或多个变量根本不使用堆栈,并在整个函数执行期间将它们保存在寄存器中。

+0

+!无法保证。 – 2009-11-06 15:19:48

4

据我所知,你甚至不能得到任何保证这些变量分配在堆栈上,它们可以存储在寄存器中。

你真的会影响什么位置:

  • 建议编译器将变量使用寄存器关键字注册。

  • 帮助编译通过,你可以移动的声明为后期地方本地化的变量范围:

 
    int f(void) 
    { 
     /* var1 and var2 probably use the same place for storage. */ 
     { 
      int var1; 
      /* ... do something */ 
     } 

     { 
      int var2; 
      /* ... do something */ 
     } 
    } 


  • 即使给出定义的范围延迟初始化:
 
{ 
    int i; /* Yes, you must declare it at the begin of block. 

    /* Do something... */ 

    i = START_VALUE; 
    /* But you need it only here and below... */ 
} 
0

如果“check_something()”很容易评估为0,那么将使用足够高的优化级别来优化整个块。是的,它依赖于编译器。通常,如果您正在检查函数调用的返回值,它将不会被优化。解决这个问题的最好方法是编译它,并实际查看文件的反汇编以验证您正在发生的事情是否正在发生。

3

如果要将变量放到堆栈中,则在该函数的第一个语句之前,函数的开头会分配堆栈空间。堆栈指针将向上(或向下)移动总字节数以存储所有本地变量。