堆栈上的本地范围记录

时间:2012-02-12 12:43:01

标签: c scope stack

考虑以下C函数 打开大括号来创建局部作用域是否会使编译器在堆栈上创建一个记录以保留作用域中声明的变量?

void function()  
{  
    int q,r;
    ...
    {  
        int i = 0;
        int j = 3;  
        q = j + 1;  
    }
    ... 
}

如果是这样,编译器对while块的行为是否相同?

示例:

void function()  
{  
    int q,r;
    ...    
    while(conditions)  
    {  
        int i = 0;  
        int j = 3;    
        q = j + 1;    
    }
    ... 
}

4 个答案:

答案 0 :(得分:4)

C标准没有规定堆栈的排列。

大括号({})引入了一个新的范围,所以原则上是的,这可以在堆栈上创建一个新的框架。但编译器可能会选择优化此开销。

答案 1 :(得分:1)

这取决于编译器。好的现代编译器会优化这段代码。它会计算

int j = 3;
q=j+1;

在编译时编写类似

的内容
q=4;

第二个例子也是如此。变量j将被置于堆栈或甚至可能位于寄存器中,其值设置为3,然后将通过循环迭代进行处理。

答案 2 :(得分:1)

{}被称为复合语句(也称为块),它引入了一个新的块作用域。这意味着:

void function(void)
{
    int q,r;
    ...

   {  
       int i = 0;
       int j = 3;  
       q = j + 1;  
   }
   ...

}

qr在函数末尾被销毁; ij在本地块范围的末尾被销毁。自动对象的生命周期仅限于声明它的块。

对于像while语句这样的迭代语句,这是完全相同的,while语句定义为:

while (expression) statement

如果对while中的语句使用复合语句(块),它还将引入新范围。

现在在堆栈级别,C不需要堆栈,因此它的实现细节。

答案 3 :(得分:0)

根据我过去看过的行为,我会说“可能不是”。 IME,只为所有函数的变量创建一个堆栈帧,无论它们在函数中的作用域如何。

受限制的范围是编译器在翻译时强制执行的操作;没有必要在运行时这样做。