【问题标题】:local scope record on the stack堆栈上的本地范围记录
【发布时间】:2012-03-04 04:00:45
【问题描述】:

考虑以下 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;    
    }
    ... 
}

【问题讨论】:

    标签: c scope stack


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      int j = 3;
      q=j+1;
      

      在编译时做类似的东西

      q=4;
      

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

      【讨论】:

        【解决方案3】:

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

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

        }

        qr 在函数结束时被销毁; ij 在本地块作用域的末尾被销毁。自动对象的生命周期仅限于声明它的块。

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

        while (expression) statement
        

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

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

        【讨论】:

        • 所以 q,r 和 i,j 可以在不同的记录上创建?
        • @user986437 q,ri,j 具有不同的词法范围和不同的生存期。
        • 请注意,while 循环中的ij 在循环的每次迭代中都会重新初始化。
        【解决方案4】:

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

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

        【讨论】:

        • 我明白了……请帮我弄清楚这一点。假设我有一台带有几 kb 内存的电脑,对程序员创建的每个范围使用记录是否有助于大型程序在我的电脑上运行?
        • 如果您的内存确实有限,为每个作用域创建一个完整的堆栈帧可能会使情况更糟。更不用说它会造成运行时性能损失。
        猜你喜欢
        • 2012-08-09
        • 2014-10-16
        • 1970-01-01
        • 2012-12-13
        • 2014-08-12
        • 2018-02-15
        • 2019-04-01
        • 2019-02-19
        • 2014-10-22
        相关资源
        最近更新 更多