【问题标题】:Can a variable declared inside a function stays in the stack even after the function call gets over in C/C++?即使在 C/C++ 中的函数调用结束后,在函数内部声明的变量能否保留在堆栈中?
【发布时间】:2020-06-23 10:54:03
【问题描述】:

下面是我的 C++ 代码。这里在函数“temp”中,首先声明“ch”的值然后打印(第一次“ch”没有初始化,所以“ch”有未定义的值)。然后“if”条件满足(在里面“如果”没有工作完成)。然后函数结束并返回到函数调用的下一行(增量'i')。然后下一次迭代也以与上一次调用相同的方式进行。相同的循环一直持续到按键被按下。当一个键被按下时(例如“a”被按下),“else”被执行并且被按下的键被 getch() 获取。然后函数结束并返回到函数调用的下一行(i++),然后在所有即将到来的下一次迭代中,当调用一个函数时,'ch' 被分配为前一个按键被按下('a')并打印该字符('一种')。它继续打印'a',直到按下另一个键。 为什么以及如何为 'ch' 分配上一个函数调用的值。上一次调用的变量值是否存储在堆栈中并将其分配给下一次调用的变量?

#include<iostream>
#include<conio.h>
#include<stdlib.h>
using namespace std;

int flag = 0,i = 1;

void temp()
{
    char ch;
    cout<<ch;
    if(!_kbhit())
    {

    }
    else{
        ch=_getch();
    }
}

int main()
{
    while(flag!=1)
    {
        temp();
        i++;
    }
   return 0;
}

【问题讨论】:

  • 如果您从遇到这种情况的构建中查看反汇编,那么您会发现这可能就是正在发生的事情。在 C/C++ 方面,行为是未定义的,而 temp() 简单地使程序崩溃的汇编代码也是有效的(与任何其他 temp() 代码一样,因为行为毕竟是未定义的)。
  • char ch; cout&lt;&lt;ch;ch 未初始化...导致UB。
  • 请提供您的全部输入和实际输出。然后解释你认为输出有什么问题。我不清楚你在问什么。也许整个例子不是很好选择要求你想要的东西。尝试将其最小化并指定问题。
  • 回答你的问题标题:可以。该变量需要使用static 进行限定,但恐怕这不是您所要求的。

标签: c++ character getch kbhit


【解决方案1】:

在您的代码中(以及在 Intel 上),在调用 temp() 并返回后,没有代码可以修改堆栈中 ch 的位置。因此,当您再次调用它时,它仍然具有以前的值。

您是否会在调用temp() 之后在main() 中调用例如printf(),然后此调用将覆盖ch 的位置。

【讨论】:

    【解决方案2】:

    要回答您的具体问题,您很幸运。

    C++ 不会不必要地清除内存。当您第二次或后续调用 temp() 时,在这种情况下,它会以与上次完全相同的方式分配内存,因此您会在 ch 中看到相同的值。

    但是,对您的程序结构或编译器设置的任何细微更改都可能意味着内存布局未对齐,您不会得到这种行为。

    按照 cmets 中的建议,将声明更改为

    static char ch;

    将保证在调用之间保留该值,而内存和性能的潜在成本非常低。

    【讨论】:

      【解决方案3】:

      “为什么以及如何为ch 分配上一个函数调用的值?”

      “上一次调用的变量ch的值是否存储在堆栈中并在下一次调用temp()时分配给ch?”

      在 C++ 中,函数本地对象不需要在函数返回后销毁,这似乎是你的情况。

      尽管如此,behavior is undefined 。您试图理解的内容是基于您执行的未定义结果。

      由于ch没有初始化,打印它的值可以输出任何值。

      它在对temp() 的所有其他函数调用中打印字符'a' 是未定义行为的标志。


      您可以通过使用static 存储类说明符限定变量ch 来找到一个明确定义的解决方案,这意味着变量ch 存储在可执行文件的BSS 段中,例如:

      static char ch;
      

      然后ch 在堆栈内存中保持活动状态,即使在使用其值的函数调用之间也是如此。

      这还具有有益的副作用,ch 会自动被 0 初始化。因此,不再有未定义的行为。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-10
        • 2017-10-21
        • 2011-10-11
        • 2013-08-13
        • 2017-01-11
        • 2019-02-08
        相关资源
        最近更新 更多