int* getINT ()
{
int y =10;
int *x = &y;
return x;
}
char* getARRAY()
{
char str[]= "Hai";
return str;
}
int Main(void)
{
char *ptr;
int *result;
result = getINT();
printf ("%d\n", *result);
ptr = getARRAY();
printf("%s", ptr);
}
在main函数中* result保持值10,而ptr具有垃圾值。我怀疑的是,为什么* str会失去范围而* x不会失去范围
答案 0 :(得分:1)
两者都是无效的,result
仍然是10比任何事情更巧合。
两次函数中的值仅在函数中存在,一旦离开函数它们就不再存在,因为两者都在函数的当前堆栈帧内的堆栈上分配。如果函数返回,则将删除堆栈帧,如果调用另一个函数,则将重用该空间。
因此,函数堆栈上的数据指针在函数外部基本没用,因为机会非常高,数据将在您尝试访问它时被覆盖。
答案 1 :(得分:1)
当您返回局部变量的地址时,该变量超出范围,该变量使用的内存位置可以重用于其他目的。试图取消引用这样的指针会调用undefined behavior。
当您调用未定义的行为时,任何事情都可能发生。您的代码可能会崩溃,可能会显示意外结果,或者可能看起来可以正常运行。对代码进行看似无关的更改(例如添加额外的未使用变量或添加/删除printf
)可能会导致该行为发生更改。
至于可能发生了什么,当你在main中填充result
时,还没有其他函数被调用,所以y
使用的堆栈空间getINT
尚未被覆盖。在下一个语句中,您取消引用该指针以获取y
的值。因为这是在调用任何函数之前完成的,所以y
的值尚未被覆盖,因此您可以获得该值。
对于ptr
,您将该指针直接传递给printf
。调用printf
的行为会写入堆栈并覆盖str
中getARRAY
先前占用的内存。
如果您在打印printf("hello\n");
之前添加*result
,则可能无法打印10
的值。同样,如果您将循环中ptr
指向的字符串复制到main
中的局部变量(不调用其他函数),则可能会恢复字符串Hai
。
但是,你不能依赖这种行为。某些编译器可能会选择在函数返回后清除堆栈上的内容。同样,更改优化级别可能会导致函数内联,因此不会发生堆栈更改。这是未定义行为的全部内容。