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

C 函数调用后指针的值是否仍然可用?,c,pointers,C,Pointers,在上面的代码“work=foo”中,我注意到“test”和“work”的值是相同的。这意味着它们指向内存中的同一点,但在函数调用“test”之后,它们超出了范围,不允许访问。为什么不允许访问“test”,但其值/内存位置是?我假设“test”由于在函数调用后脱离堆栈而不允许访问?我是新手,所以如果我的术语或任何东西不正确,请纠正我 嵌套函数不是标准的c语言,它是gcc的一种语言,因此您的代码不会一直编译,而且由于gcc扩展,它确实可以工作 之所以如此,与嵌套函数无关,如果执行以下命令,您将观察到

在上面的代码“work=foo”中,我注意到“test”和“work”的值是相同的。这意味着它们指向内存中的同一点,但在函数调用“test”之后,它们超出了范围,不允许访问。为什么不允许访问“test”,但其值/内存位置是?我假设“test”由于在函数调用后脱离堆栈而不允许访问?我是新手,所以如果我的术语或任何东西不正确,请纠正我

嵌套函数不是标准的c语言,它是gcc的一种语言,因此您的代码不会一直编译,而且由于gcc扩展,它确实可以工作

之所以如此,与嵌套函数无关,如果执行以下命令,您将观察到完全相同的行为

#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);
}

编译器将在最后一种情况下发出警告,printf%s\n正常工作;虽然工作后工作的printfvalue已由foo初始化,但仍将打印垃圾:%p\n,work;将打印相同的地址,数据将用foo的堆栈框架销毁。

嵌套函数不是标准的c,它是gcc的一个函数,因此您的代码不会总是编译,并且由于gcc扩展,它确实可以工作

之所以如此,与嵌套函数无关,如果执行以下命令,您将观察到完全相同的行为

#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);
}

编译器将在最后一种情况下发出警告,printf%s\n正常工作;虽然工作后工作的printfvalue已由foo初始化,但仍将打印垃圾:%p\n,work;如果将打印相同的地址,数据将被foo的堆栈框架破坏。

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

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

foo函数返回静态字符串Hello,该字符串通常存储在程序文本段中

由于实际的字符串存储不存在于堆栈上,因此它在函数调用后仍然存在


超出范围时的变量测试只是一个指针,由于该指针值返回给调用者,调用者现在拥有字符串存储的位置。

您的foo函数将返回静态字符串Hello,该字符串通常存储在程序文本段中

由于实际的字符串存储不存在于堆栈上,因此它在函数调用后仍然存在


超出范围的变量测试只是一个指针,由于该指针值返回给调用者,调用者现在拥有字符串存储的位置。

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

然而,在C语言中,字符串文字是具有静态存储持续时间的对象。正如您似乎错误地假设的那样,它们不会存储在堆栈上。它们存储在静态内存中,就像全局变量一样

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;
}

这就是为什么只要程序运行,字符串文字Hello的值总是可用的原因。每次调用foo时,您都会得到完全相同的指针值。

正如前面提到的,C语言中不允许使用嵌套函数

然而,在C语言中,字符串文字是具有静态存储持续时间的对象。正如您似乎错误地假设的那样,它们不会存储在堆栈上。它们存储在静态内存中,就像全局变量一样

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;
}

这就是为什么只要程序运行,字符串文字Hello的值总是可用的原因。每次调用foo时,都会返回完全相同的指针值。

这可能是因为编译器将Hello存储在一些全局内存中。然而,不要依赖这些幸运的巧合。您正在尝试的是导致未定义行为的原因。@RSahu不,这不是一个幸运的巧合,这种行为不包括嵌套函数的使用是有保证的。字符串文字具有静态存储持续时间。谢谢,没有重新设置
alize C不支持嵌套函数,并且不熟悉静态内存。这可能是因为编译器将Hello存储在某个全局内存中。然而,不要依赖这些幸运的巧合。您正在尝试的是导致未定义行为的原因。@RSahu不,这不是一个幸运的巧合,这种行为不包括嵌套函数的使用是有保证的。字符串文字具有静态存储持续时间。谢谢,我没有意识到C不支持嵌套函数,并且不熟悉静态内存。它被称为带全局变量的静态区域相同空间。它被称为带全局变量的静态区域相同空间。