关于 C 语言中指针和自动存储持续时间的问题

Question about pointers and automatic storage duration in C

提问人:Heitor E. Rezende 提问时间:12/16/2022 更新时间:12/16/2022 访问量:65

问:

我正在自己研究指针,对寿命有疑问。请看这个例子:

int* fun(){
    int arr[10];
    for(size_t c = 0;c<10;c++){
        arr[c] = c + 10;
    }
    return arr;
}


int main() {
    int* p;
    p = fun();
    printf("%p",p);
}

这个例子显然会打印一个空地址,因为数组在函数完成后被释放了。为了修复它,我尝试了 malloc 并且它奏效了。

成功后,我尝试了另一种代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

int* fun(){
    int arr[10];
    for(size_t c = 0;c<10;c++){
        arr[c] = c + 10;
    }
    int* arr2 = arr;
    return arr2;
}


int main() {
    int* p;
    p = fun();
    printf("%p",p);

}

根据我的研究,这个例子应该再次打印一个空地址,但它和 malloc 解决方案一样有效。我不明白为什么会这样。如果被释放,它的指针应该指向 null,对吧?int arr[10]

C 指针 生存期 存储持续时间

评论

5赞 tkausl 12/16/2022
If the int arr[10] is freed, it's pointers should point to null right?不,这不是 C 的工作方式。
0赞 Support Ukraine 12/16/2022
“这个例子显然会打印一个空地址”嗯......C 标准不要求这样做。根据 C 标准,它可以产生任何值。如果编译器可以检测到返回局部变量的地址,则某些编译器(例如 gcc)将返回 NULL,但标准也不要求这样做。
2赞 Support Ukraine 12/16/2022
这就是标准所说的:“当指针指向(或刚刚过去)的对象达到其生命周期的终点时,指针的值变得不确定。所以你的问题的答案是你的期望是错误的。
0赞 n. m. could be an AI 12/16/2022
“这个例子显然会打印一个空地址”你真的试过这个吗?使用哪些编译器和编译选项?

答:

1赞 Lundin 12/16/2022 #1

这个例子显然会打印一个空地址

不。从函数返回的地址将是不确定的,这意味着它没有确定性值。它可能与以前的位置相同,但编译器可以自由地打印任何它喜欢的东西,或者将整个东西视为“陷阱表示”,这意味着当这种情况发生时,它可能会抛出异常/信号等。arr

当我在 gcc 中运行您的代码时,它决定打印“(nil)”输出。虽然 clang 认为“明显”的结果应该是 .该程序还不如打印出来,这也符合要求。0x7ffef0b3c8700xDEADBEEF

根据我的研究,此示例应再次打印一个空地址

你的研究是基于错误的结论。你看了一场车祸,它倒置着地,然后得出结论,当车祸时,它们总是倒着地。

在任一示例中,返回的指针的值都是不确定的。


来源

C17 6.2.4/2:

如果在对象生存期之外引用对象,则行为是未定义的。当指针指向(或刚刚过去)的对象达到其生存期的末尾时,指针的值将变得不确定。

C17 3.19.2:

不确定值:未指定的值
或陷阱表示形式