我在页面上遇到了一个示例,概述了用C结构表示字符串的各种方法。它解释说,在main外部的函数中定义的数组将存储在堆栈段中,因此在其返回后不一定会存在,可能会导致运行时错误。
引人注目的可能的重复说明了为什么返回数组失败,即将指针推回元素0仍然有效,但没有表明相同存储类别(自动)的原因变量是成功的可以清除堆栈帧的值
“下面的程序可能会打印一些垃圾数据,因为字符串存储在函数getString()的堆栈帧中,并且在getString()返回之后数据可能不存在。”
char *getString()
{
char str[] = "GfG"; /* Stored in stack segment */
/* Problem: string may not be present after getSting() returns */
return str;
}
int main()
{
printf("%s", getString());
getchar();
return 0;
}
我知道其他局部C变量也将在它们各自的堆栈框架中定义,并且显然可以将它们返回,所以为什么数组有问题?
谢谢
答案 0 :(得分:5)
这应该大致解释发生了什么,从getString()返回后,其堆栈不再有效。
^ ^
| not valid | ^ ^
+------------+ | not valid |
str--> | "GfG" | | not valid | <---+
| --- | | not valid | |
| stack of | +------------+ |
| getString | | return(str)| ----+
+------------+ | --- |
| | | |
| stack of | | stack of |
| main() | | main() |
+------------+ +------------+
如果使用gcc -W -Wall编译(应始终使用这些选项),则应给出警告:
warning: function returns address of local variable [-Wreturn-local-addr]
答案 1 :(得分:4)
区别在于返回值与返回指针相反。
执行此操作时:
int f()
{
int x = 9;
return x;
}
int main()
{
int a = f();
printf("a=%d\n", a);
return;
}
这是有效的,因为即使x
返回时f
超出范围,它也是存储在x
中的 value (在这种情况下为9)返回。然后将该值分配给a
并随后打印。
在您的示例中,您将返回一个数组。在大多数情况下,表达式中使用的数组会衰减为指向其第一个元素的指针。因此return str
与return &str[0]
相同。该指针值将返回并传递给printf
。然后printf
试图取消对该指针的引用,但是它指向的内存(数组str
)不再有效。
因此您可以从函数中返回值,但是如果该值是指向局部变量的指针,则它将无效。
答案 2 :(得分:0)
有2种情况:
当您从本地函数返回一个简单的值,例如int
或char
时,该变量在该本地函数中定义/声明。它成功完成,因为返回值时会实际复制。
现在在"GfG"
中有字符串str
,当您执行return str
时,复制的值就是str
中的值,即阵列的地址位置。因此,在这种情况下,将复制数组位置(指针),而此数组的内容将消失(因为内容在本地堆栈帧上)。