何时为局部变量分配堆栈空间?
我对以下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进入范围时调整堆栈指针,并在它们超出范围时进行调整,但后来认为某些编译器可能只是“优化”整个事物并在嵌套范围内考虑变量。首先输入该function。
我知道我可以查看我的编译器生成的汇编代码,但是想知道实现是否可以留给编译器。
谢谢!
只要保留语言的语义 ,编译器就可以随意做任何事情。 换句话说, i2
和j2
可以在执行到达其块的入口点之前绑定到内存位置,并且可以在任何时候无限制,只要这不会影响代码的语义。
没有保证。
不同的优化标志可能会导致保存变量的不同方法。
编译器甚至可以使一个或多个变量完全不使用堆栈,并在整个函数执行期间将它们保存在寄存器中。
据我了解,即使不能保证这些变量在堆栈上分配,它们也可以存储在寄存器中。
你真正可以在这里影响到什么:
-
建议编译器使用register关键字将变量放入寄存器 。
-
通过将声明移动到尽可能晚的位置来帮助编译器本地化变量范围:
int f(void) { / * var1和var2可能使用相同的存储空间。 * / { int var1; /* ... 做一点事 */ } { int var2; /* ... 做一点事 */ } }
- 即使给定定义范围延迟初始化:
{ int i; / *是的,您必须在块的开头声明它。 /* 做一点事... */ i = START_VALUE; / *但是你只需要在这里和下面...... * / }
如果要将变量放在堆栈上,则在函数的第一个语句之前的函数开头分配堆栈空间。 堆栈指针将向上(或向下)移动总字节数以存储所有局部变量。
如果“check_something()”很容易被评估为0,那么整个块将使用足够高的优化级别进行优化。 是的,它依赖于编译器。 通常,如果您正在检查函数调用的返回值,则不会对其进行优化。 解决这个问题的最好方法是编译它,然后实际查看文件的反汇编,以validation您认为发生的事情实际发生了什么。