首页 > 解决方案 > 即使在函数返回后,在函数内部声明的非静态指针变量似乎也被保留了

问题描述

这个问题不是这个的完全重复这里最流行的答案是说不能保证内存位置会被保留,但它却意外地保留了。从我得到这段代码的地方,它清楚地表明字符串变量将被保留。

考虑以下代码:

#include<stdio.h>

char *getString()
{
    char *str = "abc";
    return str;
}     

int main()
{
   printf("%s", getString());  
   getchar();
   return 0;
}

此代码编译并运行没有任何错误。指针char* str未定义为静态变量。然而,即使在函数返回后,变量似乎也被保留了下来。

请解释这种行为。

我不明白为什么这个问题得到了反对票,即使它还没有回答或标记为重复。

标签: c

解决方案


char *getString() ... char *str = "abc";

你正在制造一些混乱。getString() 在堆栈中创建一个变量,并使其指向一个文字字符串。那个字面可以在任何地方,并且永远在那里;根据编译器的不同,它可以在启动时初始化的 RAM 中,也可以在只读存储器中。好的:如果它在 RAM 中,也许您甚至可以修改它,但不能以正常(合法)的方式 - 我们应该忽略这一点,并将其视为不可变数据。

上面的点是点。字符串“被保留”是真的。但是保留自动变量是不正确的——它可能会发生,但你不应该依赖它,如果你这样做是一个错误。根据定义,当函数返回时,自动变量会被销毁,并确保它发生。

也就是说,我不明白你怎么能说变量被保留了。C 中没有查看局部变量的机制(在当前范围之外);你可以用调试器来做,特别是当活动框架是 getString(); 也许某些调试器可以让您查看不应该查看的位置,但这是另一回事。

评论后编辑

许多编译器在堆栈中创建自动(局部)变量。当函数返回时,堆栈上的数据保持不变,因为清除/销毁堆栈只需将堆栈指针移动到其他位置即可。所以“变量似乎被保留”的肯定是正确的。似乎因为实际上变量仍然存在。似乎因为没有合法的方式使用它。但是即使在这种情况下,变量仍然存在但被隐藏,编译器可以决定使用那个房间做其他事情,或者一个中断可以到达并使用同一个房间。换句话说,当 auto 变量在作用域内时,它保证被“保留”,但是当它超出作用域时,它必须被认为是消失了。

在某些情况下,可以编写引用超出范围的变量的代码:这些是编译器应该(有时可以)检测到的错误。

我说过自动变量通常会进入堆栈。这并不总是正确的,它取决于架构和编译器,但其余的都是正确的,并且由语言规则决定。


推荐阅读