函数调用后指针的值仍然可用?

时间:2015-01-02 23:53:40

标签: c pointers

#include <stdio.h>
//needed so we can use the built in function strcpy
#include <string.h>
int main()
{
char* foo()
    {
        char* test="Hello";
        printf("value of test: %p\n",test);
        return test;

    }


    //why does this work? is test off the stack, but Hello in mem is still there?
    work=foo();
    printf("value of work after work has been initalized by foo(): %p\n",work);
    printf("%s\n",work);
}

在上面的代码中,'work = foo()',作品我注意到'test'和'work'的值是相同的。这意味着它们指向内存中的相同点,但在函数调用'test'之后超出范围并且不允许访问。为什么不允许访问'test',但其值/内存位置是?我假设由于在函数调用后离开堆栈,不允许访问'test'?我是新手,所以如果我的术语或任何内容都关闭,请纠正我。

4 个答案:

答案 0 :(得分:6)

嵌套函数不是标准c,它是gcc的extension,所以你的代码不会总是编译,并且由于gcc扩展名它可以工作。

这是真的原因与嵌套函数无关,如果执行以下操作,您将观察完全相同的行为

#include <stdio.h>

char *foo()
{
    char* test="Hello";
    printf("value of test: %p\n",test);
    return test;

}

int main()
{
    // why does this work? is test off the stack, but Hello in mem is still there?
    char *work = foo();

    printf("value of work after work has been initalized by foo(): %p\n",work);
    printf("%s\n",work);

    return 0;
}

函数foo()将地址返回到静态字符串,该字符串在程序的生命周期内保留。

我代替创建一个数组,你将地址返回到一个不可能的局部变量

#include <stdio.h>

int main()
{

    char *foo()
    {
        char test[] = "Hello";

        printf("value of test: %p\n", test);
        printf("value of foo: %p\n", foo);

        return test;
    }

    // why does this work? is test off the stack, but Hello in mem is still there?
    char *work = foo();

    printf("value of work after work has been initalized by foo(): %p\n",work);
    printf("%s\n",work);

    return 0;
}

编译器将在最后一种情况下发出警告,printf("%s\n",work);将打印垃圾,尽管printf("value of work after work has been initalized by foo(): %p\n",work);将打印相同的地址,数据将被foo的堆栈帧销毁。

答案 1 :(得分:2)

(如前所述,C语言中不允许使用嵌套函数。)

尽管如此,在C语言中,字符串文字是具有静态存储持续时间的对象。它们不会存储在堆栈中,因为您似乎错误地假设了它们。它们存储在静态存储器中,就像全局变量一样。

foo功能的代码等同于

static char unnamed_string_literal[] = { 'H', 'e', 'l', 'l', 'o', '\0' };

char* foo()
{
  char* test = unnamed_string_literal;
  printf("value of test: %p\n", test);
  return test;
}

这就是为什么只要您的程序运行,字符串文字"Hello"的值将始终可用。每当你打电话给foo时,你都会得到完全相同的指针值。

答案 2 :(得分:1)

你的foo()函数返回静态字符串&#34; Hello&#34;通常存储在程序文本段中。

由于实际的字符串存储不在堆栈上,因此它可以在函数调用中存活。

变量test虽然超出范围只是一个指针,并且由于该指针值返回给调用者,调用者现在具有字符串存储的位置。

答案 3 :(得分:0)

尽管有非标准的嵌套函数定义,但您在此处看到的行为是因为字符串常量“Hello”是程序可执行文件的一部分,并且在执行程序时会与程序代码一起映射到内存中。指针只是在运行时将内存中的位置保存在存储器中。该常量字符串是程序的一部分,并不像堆栈变量那样弹出和不存在。堆栈变量是“Hello”的地址,它通过返回值传递给调用堆栈。

相关问题