返回范围如果类型是指针,则函数值

时间:2016-10-06 14:59:54

标签: c

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不会失去范围

2 个答案:

答案 0 :(得分:1)

两者都是无效的,result仍然是10比任何事情更巧合。 两次函数中的值仅在函数中存在,一旦离开函数它们就不再存在,因为两者都在函数的当前堆栈帧内的堆栈上分配。如果函数返回,则将删除堆栈帧,如果调用另一个函数,则将重用该空间。 因此,函数堆栈上的数据指针在函数外部基本没用,因为机会非常高,数据将在您尝试访问它时被覆盖。

答案 1 :(得分:1)

当您返回局部变量的地址时,该变量超出范围,该变量使用的内存位置可以重用于其他目的。试图取消引用这样的指针会调用undefined behavior

当您调用未定义的行为时,任何事情都可能发生。您的代码可能会崩溃,可能会显示意外结果,或者可能看起来可以正常运行。对代码进行看似无关的更改(例如添加额外的未使用变量或添加/删除printf)可能会导致该行为发生更改。

至于可能发生了什么,当你在main中填充result时,还没有其他函数被调用,所以y使用的堆栈空间getINT尚未被覆盖。在下一个语句中,您取消引用该指针以获取y的值。因为这是在调用任何函数之前完成的,所以y的值尚未被覆盖,因此您可以获得该值。

对于ptr,您将该指针直接传递给printf。调用printf的行为会写入堆栈并覆盖strgetARRAY先前占用的内存。

如果您在打印printf("hello\n");之前添加*result,则可能无法打印10的值。同样,如果您将循环中ptr指向的字符串复制到main中的局部变量(不调用其他函数),则可能会恢复字符串Hai

但是,你不能依赖这种行为。某些编译器可能会选择在函数返回后清除堆栈上的内容。同样,更改优化级别可能会导致函数内联,因此不会发生堆栈更改。这是未定义行为的全部内容。